home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Draw Editor / Source / DrawEditor.cpp < prev    next >
Encoding:
Text File  |  1995-12-13  |  194.4 KB  |  6,539 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  
  3.     File:            DrawEditor.cpp
  4.     
  5.     Written by:        Dave Stafford  based on SamplePart
  6.     
  7.     Copyright:        © 1995 by Apple Computer, Inc., all rights reserved.
  8.     
  9.     Description:    DrawEditor demonstrates a fairly complete editor which supports
  10.                     native content, linking, embedding, & scripting.
  11.     
  12.     
  13.     Demonstrates:    The following recipes were used in implementing the
  14.                     DrawEditor:
  15.                      1. Open
  16.                      2. Adding A Display Frame
  17.                      3. Adding A Facet
  18.                      4. Part Drawing
  19.                      5. Refcounting Geometry
  20.                      6. ViewTypes & Presentations
  21.                      7. Display Frame 'ternalization
  22.                      8. Part Init & Externalization
  23.                      9. Part Init & partWrapper
  24.                     10. Part Storage Model
  25.                     11. Persistent Reference
  26.                     12. RefCounting
  27.                     13. Storage Unit
  28.                     14. Activation
  29.                     15. Basic Event Handling
  30.                     16. Menus
  31.                     17. Windows & Dialogs
  32.                     18. Exception Handling
  33.                     19. Memory Manager
  34.                     20. Using Resources
  35.     
  36.         
  37.     
  38.     Known Problems:    <hee hee>
  39.     
  40.     Notes:            • For methods where it is necessary to call the parent class
  41.                     implementation, the calls are made from the SOM class. See
  42.                     som_SamplePart.cpp and the Class Reference to know whether
  43.                     you need to call the parent class from any method.                    
  44.     
  45. ------------------------------------------------------------------------------*/
  46.  
  47. // Profiling
  48. #ifdef qProfileDrawEditor
  49. #include <profiler.h>
  50. #endif
  51.  
  52. // -- Compiler/Preprocessor Switches --
  53.  
  54. #ifndef _COMPILERDEFS_
  55. #include "CompDefs.h"
  56. #endif
  57.  
  58. // -- OpenDoc Utilities --
  59.  
  60. #ifndef _EXCEPT_
  61. // Exceptions define several important macros (ie. CHECKENV)
  62. // which are used in the SOM method dispatch glue. If Except.h
  63. // is not included early enough, exceptions may not be thrown
  64. // correctly when returning from a SOM method with "ev" parameter set.
  65. #include <Except.h>
  66. #endif
  67.  
  68. // -- DrawEditor Includes --
  69.  
  70. #ifndef _DRAWEDITORCONSTANTS_
  71. #include "DrawEditorConstants.h"
  72. #endif
  73.  
  74. #ifndef _DRAWEDITORUTILS_
  75. #include "DrawEditorUtils.h"
  76. #endif
  77.  
  78. #ifndef _DRAWEDITORDEF_
  79. #include "DrawEditorDef.h"
  80. #endif
  81.  
  82. #ifndef _DRAWEDTORUTILS_
  83. #include "DrawEditorUtils.h"
  84. #endif
  85.  
  86. #ifndef _DrawEditor_
  87. #include "DrawEditor.h"
  88. #endif
  89.  
  90. #ifndef _FRAMEPROXY_
  91. #include "FrameProxy.h"
  92. #endif
  93.  
  94. #ifndef _PROMISE_
  95. #include "Promise.h"
  96. #endif
  97.  
  98. #ifndef _SELECTION_
  99. #include "Selection.h"
  100. #endif
  101.  
  102. #ifndef _SHAPECOMMANDS_
  103. #include "ShapeCommands.h"
  104. #endif
  105.  
  106. #ifndef _LINKCOMMANDS_
  107. #include "LinkCommands.h"
  108. #endif
  109.  
  110. #ifndef _SHAPES_
  111. #include "Shapes.h"
  112. #endif
  113.  
  114. #ifndef _LINK_
  115. #include "Link.h"
  116. #endif
  117.  
  118. #ifndef _PALETTE_
  119. #include "Palette.h"
  120. #endif
  121.  
  122. // -- OpenDoc Includes --
  123.  
  124. #ifndef _ODTYPES_
  125. #include <ODTypes.h>
  126. #endif
  127.  
  128. #ifndef SOM_Module_OpenDoc_Global_Types_defined // For kODPresDefault
  129. #include <ODTypesM.xh>
  130. #endif
  131.  
  132. #ifndef SOM_ODPart_xh
  133. #include <Part.xh>
  134. #endif
  135.  
  136. #ifndef SOM_ODTranslation_xh
  137. #include <Translt.xh>
  138. #endif
  139.  
  140. #ifndef SOM_ODFacetIterator_xh
  141. #include <FacetItr.xh>
  142. #endif
  143.  
  144. #ifndef SOM_ODFacet_xh
  145. #include <Facet.xh>
  146. #endif
  147.  
  148. #ifndef SOM_ODClipboard_xh
  149. #include <Clipbd.xh>
  150. #endif
  151.  
  152. #ifndef SOM_ODDragItemIterator_xh
  153. #include <DgItmIt.xh>
  154. #endif
  155.  
  156. #ifndef SOM_ODDragAndDrop_xh
  157. #include <DragDrp.xh>
  158. #endif
  159.  
  160. #ifndef SOM_ODDragAndDrop_xh
  161. #include <DragDrp.xh>
  162. #endif
  163.  
  164. #ifndef SOM_ODFrame_xh
  165. #include <Frame.xh>
  166. #endif
  167.  
  168. #ifndef SOM_ODFrameFacetIterator_xh
  169. #include <FrFaItr.xh>
  170. #endif
  171.  
  172. #ifndef SOM_ODArbitrator_xh
  173. #include <Arbitrat.xh>
  174. #endif
  175.  
  176. #ifndef SOM_Module_OpenDoc_Foci_defined
  177. #include <Foci.xh>
  178. #endif
  179.  
  180. #ifndef SOM_ODShape_xh
  181. #include <Shape.xh>
  182. #endif
  183.  
  184. #ifndef SOM_Module_OpenDoc_StdProps_defined
  185. #include <StdProps.xh>
  186. #endif
  187.  
  188. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  189. #include <StdTypes.xh>
  190. #endif
  191.  
  192. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  193. #include <StdDefs.xh>
  194. #endif
  195.  
  196. #ifndef SOM_Module_OpenDoc_Commands_defined
  197. #include <CmdDefs.xh>
  198. #endif
  199.  
  200. #ifndef SOM_ODDraft_xh
  201. #include <Draft.xh>
  202. #endif
  203.  
  204. #ifndef SOM_ODStorageUnit_xh
  205. #include <StorageU.xh>
  206. #endif
  207.  
  208. #ifndef SOM_ODStorageUnitView_xh
  209. #include <SUView.xh>
  210. #endif
  211.  
  212. #ifndef SOM_ODLinkSrc_xh
  213. #include <LinkSrc.xh>
  214. #endif
  215.  
  216. #ifndef SOM_ODLink_xh
  217. #include <Link.xh>
  218. #endif
  219.  
  220. #ifndef SOM_ODTransform_xh
  221. #include <Trnsform.xh>
  222. #endif
  223.  
  224. #ifndef SOM_ODFocusSet_xh
  225. #include <FocusSet.xh>
  226. #endif
  227.  
  228. #ifndef SOM_ODMenuBar_xh
  229. #include <MenuBar.xh>
  230. #endif
  231.  
  232. #ifndef SOM_ODWindow_xh
  233. #include <Window.xh>
  234. #endif
  235.  
  236. #ifndef SOM_ODWindowState_xh
  237. #include <WinStat.xh>
  238. #endif
  239.  
  240. #ifndef SOM_ODCanvas_xh
  241. #include <Canvas.xh>
  242. #endif
  243.  
  244. #ifndef SOM_ODSession_xh
  245. #include <ODSessn.xh>
  246. #endif
  247.  
  248. // -- OpenDoc Utilities --
  249.  
  250. #ifndef _NMSPCUTL_
  251. #include <NmSpcUtl.h>
  252. #endif
  253.  
  254. #ifndef _BNDNSUTL_
  255. #include <BndNSUtl.h>
  256. #endif
  257.  
  258. #ifndef _STDTYPIO_
  259. #include <StdTypIO.h>
  260. #endif
  261.  
  262. #ifndef SOM_ODInfo_xh
  263. #include <Info.xh>
  264. #endif
  265.  
  266. #ifndef _TEMPOBJ_
  267. #include <TempObj.h>
  268. #endif
  269.  
  270. #ifndef _TEMPITER_
  271. #include <TempIter.h>
  272. #endif
  273.  
  274. #ifndef _ODUTILS_
  275. #include <ODUtils.h>
  276. #endif
  277.  
  278. #ifndef _STDTYPIO_
  279. #include <StdTypIO.h>
  280. #endif
  281.  
  282. #ifndef _ORDCOLL_
  283. #include "OrdColl.h"
  284. #endif
  285.  
  286. #ifndef _ODDEBUG_
  287. #include <ODDebug.h>
  288. #endif
  289.  
  290. #ifndef _ITEXT_
  291. #include <IText.h>
  292. #endif
  293.  
  294. #ifndef _FOCUSLIB_
  295. #include <FocusLib.h>
  296. #endif
  297.  
  298. #ifndef _USERSRCM_
  299. #include <UseRsrcM.h>
  300. #endif
  301.  
  302. #ifndef _ODMEMORY_
  303. #include <ODMemory.h>
  304. #endif
  305.  
  306. #ifndef _ISOSTR_
  307. #include <ISOStr.h>
  308. #endif
  309.  
  310. #ifndef _PLFMDEF_
  311. #include <PlfmDef.h>
  312. #endif
  313.  
  314. #ifndef _PASCLSTR_
  315. #include <PasclStr.h>
  316. #endif
  317.  
  318. #ifndef _STORUTIL_
  319. #include <StorUtil.h>
  320. #endif
  321.  
  322. #ifndef _WINUTILS_
  323. #include <WinUtils.h>
  324. #endif
  325.  
  326. #ifndef _UTILERRS_
  327. #include <UtilErrs.h>
  328. #endif
  329.  
  330. // -- Macintosh Includes --
  331.  
  332. #ifndef __ERRORS__
  333. #include <Errors.h>
  334. #endif
  335.  
  336. #ifndef __RESOURCES__
  337. #include <Resources.h>
  338. #endif
  339.  
  340. #ifndef __DIALOGS__
  341. #include <Dialogs.h>
  342. #endif
  343.  
  344. #ifndef __TOOLUTILS__
  345. #include <ToolUtils.h>
  346. #endif
  347.  
  348. #ifndef __ICONS__
  349. #include <Icons.h>
  350. #endif
  351.  
  352. #ifndef __QUICKDRAW__
  353. #include <Quickdraw.h>
  354. #endif
  355.  
  356. #ifndef __LOWMEM__
  357. #include <LowMem.h>
  358. #endif
  359.  
  360. #ifndef mathRoutinesIncludes
  361. #include <math routines.h>
  362. #endif
  363.  
  364. #pragma segment DrawEditor
  365.  
  366. //==============================================================================
  367. // DrawEditor
  368. //==============================================================================
  369.  
  370. //------------------------------------------------------------------------------
  371. // Method:        Constructor
  372. // Origin:        DrawEditor
  373. //
  374. // Description:    This is the C++ class constructor.
  375. //
  376. // Warnings:    You are not allowed to throw an exception from this
  377. //                method.
  378. //------------------------------------------------------------------------------
  379.  
  380. DrawEditor::DrawEditor()
  381. {
  382.     SOM_Trace("DrawEditor","somInit");
  383.         
  384.     fGroupCount            = 0L;
  385.     fShapeList            = kODNULL;
  386.     fEmbeddedFrames        = kODNULL;
  387.     fHilightedDragFacet    = kODNULL;
  388.     fActiveBorderShape    = kODNULL;
  389.     
  390.     fDisplayFrameProxies= kODNULL;
  391.     fDirty                = kODFalse;
  392.     fSelf                = kODNULL;
  393.     fReadOnlyStorage    = kODFalse;
  394.     fLinkStatus            = kODNotInLink;
  395.     
  396.     fSelection    = kODNULL;
  397.  
  398.     fPendingPublish = kODNULL;
  399.     fPendingDragPublish = kODNULL;
  400.     
  401.     fPublishLinks = kODNULL;
  402.     fSubscribeLinks = kODNULL;
  403.  
  404.     fPartContent = kODNULL;
  405.  
  406. }
  407.  
  408. //------------------------------------------------------------------------------
  409. // Method:        Destructor
  410. // Origin:        DrawEditor
  411. //
  412. // Description:    This is the SOM equivalent of a C++ class destructor.
  413. //                In this routine, you should clean up any class members
  414. //                which were not cleaned up in the ReleaseAll and
  415. //                Release methods; and finally call you parent class's
  416. //                somUninit (destructor) method.
  417. //
  418. // Warnings:    You are not allowed to throw an exception from this
  419. //                method.
  420. //------------------------------------------------------------------------------
  421.  
  422. DrawEditor::~DrawEditor()
  423. {
  424.     SOM_Trace("DrawEditor","somUninit");
  425.  
  426.     // Delete the current selection
  427.     if (fSelection)
  428.         delete fSelection;
  429.     
  430.     // Delete the shape list
  431.     if (fShapeList)
  432.         delete fShapeList;
  433.  
  434.     // Delete the shape list
  435.     if (fEmbeddedFrames)
  436.         delete fEmbeddedFrames;
  437.  
  438.     // Delete the subscribe links
  439.     if (fSubscribeLinks)
  440.         delete fSubscribeLinks;
  441.     
  442.     // Delete the publish links;
  443.     if (fPublishLinks)
  444.         delete fPublishLinks;
  445.  
  446.     // Delete the content object
  447.     if (fPartContent)
  448.         delete fPartContent;
  449. }
  450.  
  451. //------------------------------------------------------------------------------
  452. // Method:        GetODPart
  453. // Origin:        DrawEditor
  454. //
  455. // Description:    Return the part wrapper of the ODPart whose implementation is
  456. // provided by this class.
  457. //
  458. // Warnings:    
  459. //------------------------------------------------------------------------------
  460.  
  461. ODPart* DrawEditor::GetODPart() const
  462. {
  463.     return fSelf;
  464. }
  465.  
  466. //------------------------------------------------------------------------------
  467. // Method:        GetEditorKind
  468. // Origin:        DrawEditor
  469. //
  470. // Description:    Return the ODValuType representing the type of data we edit.
  471. //
  472. // Warnings:    
  473. //------------------------------------------------------------------------------
  474.  
  475. ODValueType DrawEditor::GetEditorKind() const
  476. {
  477.     return kDrawEditorKind;
  478. }
  479.  
  480. //------------------------------------------------------------------------------
  481. // Method:        GetEditorKind
  482. // Origin:        DrawEditor
  483. //
  484. // Description:    Return the current Link Status.
  485. //
  486. // Warnings:    
  487. //------------------------------------------------------------------------------
  488.  
  489. ODLinkStatus DrawEditor::GetLinkStatus() const
  490. {
  491.     return fLinkStatus;
  492. }
  493.  
  494. //------------------------------------------------------------------------------
  495. // Method:        IsReadOnly
  496. // Origin:        DrawEditor
  497. //
  498. // Description:    Return a reference to the current session.
  499. //
  500. //------------------------------------------------------------------------------
  501.  
  502. ODBoolean DrawEditor::IsReadOnly()
  503. {
  504.     return fReadOnlyStorage;
  505. }
  506.  
  507.  
  508. //------------------------------------------------------------------------------
  509. // Method:        GetSession
  510. // Origin:        DrawEditor
  511. //
  512. // Description:    Return a reference to the current session.
  513. //
  514. //------------------------------------------------------------------------------
  515.  
  516. ODSession* DrawEditor::GetSession(Environment* ev) const
  517. {
  518.     ODPart* tPart = GetODPart();
  519.     ODStorageUnit* tStorage = tPart->GetStorageUnit(ev);
  520.     ODSession* tSession = tStorage->GetSession(ev);
  521.     
  522.     return tSession;
  523. }
  524.  
  525.  
  526. //------------------------------------------------------------------------------
  527. // Method:        GetDraft
  528. // Origin:        DrawEditor
  529. //
  530. // Description:    Return a reference to this part's draft.
  531. //
  532. //------------------------------------------------------------------------------
  533.  
  534. ODDraft* DrawEditor::GetDraft(Environment* ev) const
  535. {
  536.     return GetODPart()->GetStorageUnit(ev)->GetDraft(ev);
  537. }
  538.  
  539.  
  540. //------------------------------------------------------------------------------
  541. // Method:        GetShapeList
  542. // Origin:        DrawEditor
  543. //
  544. // Description:    Return a list of my shapes.
  545. //
  546. //------------------------------------------------------------------------------
  547.  
  548. COrderedList* DrawEditor::GetShapeList() const
  549. {
  550.     return fShapeList;
  551. }
  552.  
  553.  
  554. //------------------------------------------------------------------------------
  555. // Method:        GetEmbeddedFrames
  556. // Origin:        DrawEditor
  557. //
  558. // Description:    Return a list of my embeddedFrames.
  559. //
  560. //------------------------------------------------------------------------------
  561.  
  562. COrderedList* DrawEditor::GetEmbeddedFrames() const
  563. {
  564.     return fEmbeddedFrames;
  565. }
  566.  
  567.  
  568. //------------------------------------------------------------------------------
  569. // Method:        GetFirstSourceFrame
  570. // Origin:        DrawEditor
  571. //
  572. // Description:    
  573. //------------------------------------------------------------------------------
  574. ODFrame* DrawEditor::GetFirstSourceFrame (Environment* ev)
  575. {        
  576.     if ( fDisplayFrameProxies )
  577.     {
  578.         COrdListIterator fiter(fDisplayFrameProxies);
  579.         for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  580.                 fiter.IsNotComplete();
  581.                 frameProxy=(CDisplayFrameProxy*)fiter.Next())
  582.         {
  583.             // This will cause the frame to internalize
  584.             ODFrame* frame = frameProxy->GetFrame(ev);
  585.             CFrameInfo* info = (CFrameInfo*) frame->GetPartInfo(ev);
  586.  
  587.             if (( frame->GetPresentation(ev) == gGlobals->fMainPresentation ) &&
  588.                 ( frame->GetViewType(ev) == gGlobals->fFrameView )&&!info->HasSourceFrame())
  589.                 {
  590.                     return frame;
  591.                 }
  592.         }
  593.     }
  594.     return kODNULL;
  595. }
  596.  
  597.  
  598. //------------------------------------------------------------------------------
  599. // Method:        GetANYFrame
  600. // Origin:        DrawEditor
  601. //
  602. // Description:    Since frames have ceratin facilities ( namely object factory
  603. // methods ) there are times that having guaranteed access to ANY frame is
  604. // necessary.
  605. //------------------------------------------------------------------------------
  606.  
  607. ODFrame* DrawEditor::GetANYFrame(Environment* ev) const
  608. {
  609.     if ( fDisplayFrameProxies )
  610.     {
  611.         COrdListIterator fiter(fDisplayFrameProxies);
  612.         for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  613.                 fiter.IsNotComplete();
  614.                 frameProxy=(CDisplayFrameProxy*)fiter.Next())
  615.         {
  616.             if (frameProxy->IsFrameInMemory())
  617.             {
  618.                 return frameProxy->GetFrame(ev);
  619.             }
  620.         }
  621.     }
  622.     
  623.     #ifdef ODDebug
  624.         DebugStr("\p Didn't get a frame! Need to work harder..");
  625.     #endif
  626.     
  627.     return kODNULL;
  628. }
  629.  
  630.  
  631. //------------------------------------------------------------------------------
  632. // Method:        GetContentDisplayFrames
  633. // Origin:        DrawEditor
  634. //
  635. // Description:    Return a list of the frames whose presentation is 
  636. // gGlobals->fMainPresentation AND whose view type is frame.
  637. //
  638. // This method is useful for when the part, or a client of the editor needs access 
  639. // to just the display frames of the editor which are currently displaying content.    
  640. //
  641. // NOTE: The caller must delete the list pointer ( not the links ) that is returned.
  642. //------------------------------------------------------------------------------
  643.  
  644. COrderedList* DrawEditor::GetContentDisplayFrames(Environment* ev) const
  645. {
  646.     COrderedList* theList = kODNULL;
  647.     
  648.     if ( fDisplayFrameProxies )
  649.     {
  650.         COrdListIterator fiter(fDisplayFrameProxies);
  651.         for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  652.                 fiter.IsNotComplete();
  653.                 frameProxy=(CDisplayFrameProxy*)fiter.Next())
  654.         {
  655.             // This will cause the frame to internalize
  656.             ODFrame* frame = frameProxy->GetFrame(ev);
  657.             
  658.             if (( frame->GetPresentation(ev) == gGlobals->fMainPresentation ) &&
  659.                 ( frame->GetViewType(ev) == gGlobals->fFrameView ))
  660.             {
  661.                 // Only create the list if we find any
  662.                 if (!theList)
  663.                     theList = new COrderedList;
  664.                 
  665.                 // Add the found frame to the list    
  666.                 theList->AddLast(frame);
  667.             }
  668.         }
  669.     }
  670.  
  671.     return theList;
  672. }
  673.  
  674.  
  675. //------------------------------------------------------------------------------
  676. // Method:        GetGroupCount
  677. // Origin:        DrawEditor
  678. //
  679. // Description:    Return the last GroupID generated by this part instance.
  680. //------------------------------------------------------------------------------
  681.  
  682. ODULong DrawEditor::GetGroupCount() const
  683. {
  684.     return fGroupCount;
  685. }
  686.  
  687. //------------------------------------------------------------------------------
  688. // Method:        GetNewGroupID
  689. // Origin:        DrawEditor
  690. //
  691. // Description:    Return the next GroupID generated by this part instance.
  692. //------------------------------------------------------------------------------
  693.  
  694. ODULong DrawEditor::GetNewGroupID()
  695. {
  696.     fGroupCount++;
  697.     return this->GetGroupCount();
  698. }
  699.  
  700. //------------------------------------------------------------------------------
  701. // Method:        GetRootFacetOfActiveWindow
  702. // Origin:        DrawEditor
  703. //
  704. // Description:    Return a reference to the root facet of the active window.
  705. //
  706. // This method is useful for when the part, or a client of the part needs access to
  707. // a factory method of facet and has no other access to facets.    
  708. //------------------------------------------------------------------------------
  709.  
  710. ODFacet* DrawEditor::GetRootFacetOfActiveWindow(Environment* ev) const
  711. {
  712.     ODFacet* facet = kODNULL;
  713.     TRY
  714.         // Acquire the active window
  715.         TempODWindow window = this->GetSession(ev)->GetWindowState(ev)->AcquireActiveWindow(ev);
  716.         THROW_IF_NULL(window);
  717.         
  718.         facet = window->GetRootFacet(ev);
  719.     CATCH_ALL
  720.         #ifdef ODDebug
  721.         DebugStr("\p Trouble getting root facet of active window!");
  722.         #endif
  723.     ENDTRY
  724.     
  725.     return facet;
  726. }
  727.  
  728.  
  729. //------------------------------------------------------------------------------
  730. // Method:        InitPart
  731. // Origin:        ODPart
  732. //
  733. // Description:    This method is called when a new instance of this part
  734. //                is being created. The part should write out all the
  735. //                standard properties and values that the part expects
  736. //                to see.
  737. //
  738. // Warning:        It is not appropriate to require user interaction while
  739. //                stationery is being created. Do not present the user
  740. //                with error dialogs or splash screens from this method.
  741. //------------------------------------------------------------------------------
  742.  
  743. void DrawEditor::InitPart( Environment*        ev,
  744.                            ODStorageUnit*    storageUnit,
  745.                            ODPart*            partWrapper )
  746. {
  747.     SOM_Trace("DrawEditor","InitPart");
  748.  
  749.     TRY
  750.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  751.         // that we pass in a "reference" to ourselves when interacting with the
  752.         // API (ie. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  753.         // The "partWrapper" passed to us here and in InitPartFromStorage is the
  754.         // "reference" OpenDoc is asking us to use.
  755.         fSelf = partWrapper;
  756.             
  757.         // We are being created, either as part of generating stationery or
  758.         // by some editor instantiating the part, so the destination storage
  759.         // must be writeable.
  760.         fReadOnlyStorage = kODFalse;
  761.             
  762.         // Call the common initialization code to get set up.
  763.         this->Initialize(ev);
  764.  
  765.         // Since we have just been created, our state/content info has
  766.         // never been written out, so setting our "dirty" flag will
  767.         // give us a chance to do that.
  768.         
  769.         this->SetDirty(ev);
  770.     
  771.     CATCH_ALL
  772.         ODSetSOMException(ev, ErrorCode());
  773.  
  774.         // Clean up will occur in the destructor which will be called
  775.         // shortly after we return the error.
  776.         RERAISE;
  777.     ENDTRY
  778. }
  779.  
  780. //------------------------------------------------------------------------------
  781. // Method:        InitPartFromStorage
  782. // Origin:        ODPart
  783. //
  784. // Description:    This method is called when a document/stationery is
  785. //                being opened or when the part is internalized by its
  786. //                containing part. The part should merely read in the
  787. //                saved state/content and initialize itself. The part
  788. //                 must not alter its storage unit; otherwise, the "Save"
  789. //                 menu item becomes enabled without the user actually
  790. //                having made a change to the document.
  791. //------------------------------------------------------------------------------
  792.  
  793. void DrawEditor::InitPartFromStorage( Environment*        ev,
  794.                                       ODStorageUnit*    storageUnit,
  795.                                       ODPart*            partWrapper )
  796. {
  797.     SOM_Trace("DrawEditor","InitPartFromStorage");
  798.  
  799.     TRY
  800.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  801.         // that we pass in a "reference" to ourselves when interacting with the
  802.         // API (ie. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  803.         // The "partWrapper" passed to us here and in InitPart is the
  804.         // "reference" OpenDoc is asking us to use.
  805.         fSelf = partWrapper;
  806.             
  807.         // Are we being opened from a read-only draft? If so, we cannot
  808.         // write anything back out to our storage unit.
  809.         fReadOnlyStorage = ( this->GetDraft(ev)->
  810.                                         GetPermissions(ev) == kODDPReadOnly );
  811.             
  812.         // Call the common initialization code to get set up.
  813.         this->Initialize(ev);
  814.     
  815.         // Read in the state the part was in when it was last Externalized.
  816.         // This allows the part to present the same "environment" the user
  817.         // had the part set up in the last time it was edited.
  818.         this->InternalizeStateInfo(ev, storageUnit);
  819.     
  820.         // Read in the contents for your part editor.
  821.         this->InternalizeContent(ev, storageUnit);
  822.  
  823.     CATCH_ALL
  824.         ODSetSOMException(ev, ErrorCode());
  825.  
  826.         // Clean up will occur in the destructor which will be called
  827.         // shortly after we return the error.
  828.         RERAISE;
  829.     ENDTRY
  830. }
  831.  
  832. //------------------------------------------------------------------------------
  833. // Method:        Initialize
  834. // Origin:        DrawEditor
  835. //
  836. // Description:    This method is called during the internalization of
  837. //                the part from a document. The methods purpose is to 
  838. //                initialize all fields of the part and to convert 
  839. //                ISO types to tokens for faster comparisons throughout
  840. //                the code.
  841. //------------------------------------------------------------------------------
  842.  
  843. void DrawEditor::Initialize( Environment*    ev )
  844. {
  845.     SOM_Trace("DrawEditor","Initialize");
  846.  
  847.     // Profiling
  848.     #ifdef qProfileDrawEditor
  849.     OSErr err = ::ProfilerInit(collectDetailed, ticksTimeBase, 200, 22);
  850.     ::ProfilerSetStatus(kODFalse);
  851.     #endif
  852.     
  853.     // Grab a reference to the Session object. This is merely for
  854.     // convenience.
  855.     ODSession* session = GetODPart()->GetStorageUnit(ev)->GetSession(ev);
  856.         
  857.     // Create a list to keep track of the facets we are being
  858.     // displayed in. Also used for maintenance (i.e., Purging memory).
  859.     fDisplayFrameProxies = new COrderedList;
  860.  
  861.     fShapeList = new COrderedList;
  862.     fPublishLinks = new COrderedList;
  863.     fSubscribeLinks = new COrderedList;
  864.  
  865.     // Create a content object which knows how to internalize and externalize
  866.     fPartContent = new CPartContent(this, fShapeList, fPublishLinks, fSubscribeLinks);
  867.     
  868.     // Create a list to keep track of the embedded frames we have. 
  869.     fEmbeddedFrames = new COrderedList;
  870.  
  871.     // Instantiate the current selection
  872.     fSelection = new CSelection(this, kODFalse, kODFalse);
  873.  
  874.     // First check to see if the library's global variables have
  875.     // been initialized (meaning another part instantiation is already
  876.     // running).
  877.  
  878.     if ( gGlobalsUsageCount == 0 )
  879.     {
  880.         // Allocate globals structure
  881.         gGlobals = new DrawEditorGlobals;
  882.         
  883.         // Acces our resource file
  884.         ODSLong        savedRefNum;
  885.         savedRefNum = BeginUsingLibraryResources();
  886.         
  887.         // Load our floating window def proc in case the 7.5 def proc
  888.         // is not available ( could check system version here.. ).
  889.         gGlobals->fFloatWindowProc = ::GetResource('WDEF', kFloatWindowDefID);    
  890.         
  891.         EndUsingLibraryResources(savedRefNum);
  892.             
  893.         
  894.         // Cache the ISO representation o 'TEXT' so we don't have to call 
  895.         // translation every time
  896.         ODTranslation* translation = this->GetSession(ev)->GetTranslation(ev); 
  897.         gGlobals->fCurrentTextPartKind = translation->GetISOTypeFromPlatformType(ev, 
  898.                                                         'TEXT', kODPlatformDataType);
  899.                 
  900.         // It is required that parts instantiate their menu bars from 
  901.         // the base OpenDoc menu bar. This maintains consistency in the
  902.         // default menu items and their placement.
  903.         // Since the object is a copy, we can add and subtract menus and
  904.         // items without affecting other running parts.
  905.         gGlobals->fMenuBar = session->GetWindowState(ev)->CopyBaseMenuBar(ev);
  906.  
  907.         // Load and register our menus
  908.         this->LoadMenus(ev);
  909.  
  910.         // We will be using the following foci (shared resources) in this
  911.         // part. For convenience, we tokenize the values here and store
  912.         // them for equivalence tests in the activation methods.
  913.         gGlobals->fClipboardFocus = session->Tokenize(ev, kODClipboardFocus);
  914.         gGlobals->fSelectionFocus = session->Tokenize(ev, kODSelectionFocus);
  915.         gGlobals->fMenuFocus      = session->Tokenize(ev, kODMenuFocus);
  916.         gGlobals->fModalFocus   = session->Tokenize(ev, kODModalFocus);
  917.         gGlobals->fKeyFocus       = session->Tokenize(ev, kODKeyFocus);
  918.     
  919.         // If we don't acquire the key focus as a part of our focus set
  920.         // then embedded text editors will leave carets lying around.
  921.         // It would also be necessary if nudge were implemented.
  922.         gGlobals->fKeyFocus     = session->Tokenize(ev, kODKeyFocus);
  923.     
  924.         // Also for convenience, we tokenize our part's main presentation
  925.         // and the standard view types.
  926.         gGlobals->fMainPresentation = session->Tokenize(ev, kMainPresentation);
  927.         gGlobals->fUndefinedPresentation = session->Tokenize(ev, kODPresDefault);
  928.         
  929.         gGlobals->fFrameView         = session->Tokenize(ev, kODViewAsFrame);
  930.         gGlobals->fLargeIconView     = session->Tokenize(ev, kODViewAsLargeIcon);
  931.         gGlobals->fSmallIconView     = session->Tokenize(ev, kODViewAsSmallIcon);
  932.         gGlobals->fThumbnailView     = session->Tokenize(ev, kODViewAsThumbnail);
  933.     
  934.         // Allocate the Color & Tool Palettes
  935.         gGlobals->fColorPalette = new CColorPalette(this);
  936.         gGlobals->fToolPalette = new CToolPalette(this);
  937.         
  938.         // Cache black as it is represented in our color palette
  939.         gGlobals->fBlackColor = new CRGBColor();
  940.         gGlobals->fColorPalette->GetColor(kBlackColor, gGlobals->fBlackColor);
  941.         
  942.         // Lastly, we will package the menu and selection focus
  943.         // so that we can request the "set" at activation time.
  944.         gGlobals->fUIFocusSet = session->GetArbitrator(ev)->CreateFocusSet(ev);
  945.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fMenuFocus);
  946.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fSelectionFocus);
  947.         gGlobals->fUIFocusSet->Add(ev, gGlobals->fKeyFocus);
  948.                     
  949.         // Determine what Script/Language the part is localized for.
  950.         // This is important/necessary for creating OpenDoc's text objects.
  951.         GetEditorScriptLanguage(ev, &gGlobals->fEditorsScript, &gGlobals->fEditorsLanguage);
  952.         
  953.         // The first client of the global variables is running.
  954.         gGlobalsUsageCount = 1;
  955.     }
  956.     else
  957.     // If the globals have been initialized, we just bump the refcount of the
  958.     // menu bar. This prevents will prevent it from going away before we are
  959.     // done using it. We also keep a "usage" count so that we can null out the
  960.     // global variables when we are finished using them.
  961.     {
  962.         gGlobalsUsageCount++;
  963.     }
  964. }
  965.  
  966.  
  967.  
  968. //------------------------------------------------------------------------------
  969. // Method:        LoadMenus
  970. // Origin:        DrawEditor
  971. //
  972. // Description:    This method is called the first time  an instance
  973. //                of this part is initalized to create DrawEditor
  974. //                specific menus and add them to the menubar.
  975. //
  976. // Warning:        This method assumes that the global gGlobals->fMenuBar has been initialized.
  977. //------------------------------------------------------------------------------
  978.  
  979. void DrawEditor::LoadMenus( Environment* ev )
  980. {
  981.     SOM_Trace("DrawEditor","LoadMenus");
  982.  
  983.     // Load menu resources and add them to the menubar
  984.     ODSLong ref;
  985.     ref = BeginUsingLibraryResources();
  986.         
  987.     TRY    
  988.         gGlobals->fMenuBar->AddMenuLast(ev, kLayoutMenuID, GetMenu(kLayoutMenuID), GetODPart());
  989.         gGlobals->fMenuBar->AddMenuLast(ev, kPalettesMenuID, GetMenu(kPalettesMenuID), GetODPart());
  990.  
  991.     CATCH_ALL
  992.         #ifdef ODDebug
  993.         DebugStr("\p Add of menu failed!");
  994.         #endif
  995.     
  996.     ENDTRY
  997.     
  998.     EndUsingLibraryResources(ref);
  999.     
  1000.     // Layout Menu
  1001.     gGlobals->fMenuBar->RegisterCommand( ev, kMoveForwardCmd, kLayoutMenuID, kMoveForwardItem );
  1002.     gGlobals->fMenuBar->RegisterCommand( ev, kMoveFrontCmd, kLayoutMenuID, kMoveFrontItem );
  1003.     gGlobals->fMenuBar->RegisterCommand( ev, kMoveBackwardCmd, kLayoutMenuID, kMoveBackwardItem );
  1004.     gGlobals->fMenuBar->RegisterCommand( ev, kMoveBackCmd, kLayoutMenuID, kMoveBackItem );
  1005.     // gGlobals->fMenuBar->RegisterCommand(ev, kWrapToParItem, kLayoutMenuID, kWrapToPartCmd);
  1006.     
  1007.     // Palettes Menu
  1008.     gGlobals->fMenuBar->RegisterCommand( ev, kShowHideToolPaletteCmd, kPalettesMenuID, kToolPaletteItem );
  1009.     gGlobals->fMenuBar->RegisterCommand( ev, kShowHideColorPaletteCmd, kPalettesMenuID, kColorPaletteItem );
  1010.  
  1011. }
  1012.  
  1013. //------------------------------------------------------------------------------
  1014. // Method:        AdjustMenus
  1015. //
  1016. // Description:    This method is called when a kODEvtMouseDown event
  1017. //                occurs in the menubar and the part owns the "menu"
  1018. //                focus.
  1019. //
  1020. //                The part enables the appropriate items for its current
  1021. //                state and updates the menu items to reflect this
  1022. //                editor.
  1023. //------------------------------------------------------------------------------
  1024.  
  1025. void DrawEditor::AdjustMenus( Environment*    ev,
  1026.                               ODFrame*        frame )
  1027. {
  1028.     SOM_Trace("DrawEditor","AdjustMenus");
  1029.  
  1030.     // Enable the "View As Window" command always while we are not the root part.
  1031.     gGlobals->fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev));
  1032.     
  1033.     // Change the "About" menu item text for our part.
  1034.     ::SetMenuItemText( ev, kODCommandAbout, kAboutTextID );
  1035.         
  1036.     // Change the text for the color palette menu item
  1037.     if (gGlobals->fColorPalette->IsShown(ev))
  1038.         ::SetMenuItemText( ev, kShowHideColorPaletteCmd, kHideColorPaletteIndex );
  1039.     else
  1040.         ::SetMenuItemText( ev, kShowHideColorPaletteCmd, kShowColorPaletteIndex );
  1041.  
  1042.     // Change the text for the tool palette menu item
  1043.     if (gGlobals->fToolPalette->IsShown(ev))
  1044.         ::SetMenuItemText( ev, kShowHideToolPaletteCmd, kHideToolPaletteIndex );
  1045.     else
  1046.         ::SetMenuItemText( ev, kShowHideToolPaletteCmd, kShowToolPaletteIndex );
  1047.  
  1048.  
  1049.     // File menu
  1050.     gGlobals->fMenuBar->EnableCommand(ev, kODCommandOpen, !fSelection->IsEmpty());
  1051.     
  1052.     ODBoolean canModify = !this->IsReadOnly();
  1053.     ODBoolean canClear = canModify && fSelection->CanMoveSelectedContent();
  1054.     
  1055.     // Edit menu
  1056.     if (fSelection->IsOneLink())
  1057.     {
  1058.         ::SetMenuItemText( ev, kODCommandGetPartInfo, kLinkInfoIndex );
  1059.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandGetPartInfo, kODTrue);
  1060.     }
  1061.     else
  1062.     {
  1063.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandGetPartInfo, 
  1064.                 fSelection->IsOneEmbeddedShape(ev)!=kODNULL);
  1065.     }
  1066.     
  1067.     gGlobals->fMenuBar->EnableCommand(ev, kODCommandClear, canClear);
  1068.     gGlobals->fMenuBar->EnableCommand(ev, kODCommandSelectAll, fShapeList->Count()>0);
  1069.  
  1070.     // Clipboard
  1071.     ODArbitrator* tArbitrator = this->GetSession(ev)->GetArbitrator(ev);
  1072.     ODFrame* clipboardFocusOwner = tArbitrator->AcquireFocusOwner(ev, gGlobals->fClipboardFocus);
  1073.     if ( (frame == clipboardFocusOwner) || 
  1074.          (tArbitrator->RequestFocus(ev, gGlobals->fClipboardFocus, frame)) )
  1075.     {
  1076.         
  1077.         // This will allow the pasting of foreign content.  
  1078.         // Pass kODNULL for the kind, to just test for content.
  1079.         ODBoolean canPaste = canModify && ValueOnClipboard(ev, kODNULL, this->GetSession(ev));
  1080.         
  1081.         // enable cut only if we have a selection and the draft is modifiable
  1082.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandCut, canClear);
  1083.         
  1084.         // Can only copy if we have a selection
  1085.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandCopy, !fSelection->IsEmpty());
  1086.         
  1087.         // enable paste only if we support the type available & the drafts modifiable
  1088.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandPaste, canPaste);
  1089.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandPasteAs, canPaste);
  1090.     }
  1091.     ODReleaseObject(ev, clipboardFocusOwner);
  1092.  
  1093.     // It's ok to re-order a link destinations as a whole with respect to the other
  1094.     // shapes, but it does not make sense to reorder part's of them. Since currently
  1095.     // link updates don't respect order at all, this may be moot.
  1096.     gGlobals->fMenuBar->EnableCommand(ev, kMoveForwardCmd, canClear);
  1097.     gGlobals->fMenuBar->EnableCommand(ev, kMoveFrontCmd, canClear);
  1098.     gGlobals->fMenuBar->EnableCommand(ev, kMoveBackwardCmd, canClear);
  1099.  
  1100. }
  1101.  
  1102.  
  1103. //------------------------------------------------------------------------------
  1104. // Method:        Release
  1105. // Origin:        ODPart
  1106. //
  1107. // Description:    This method is called each time an object releases the
  1108. //                part. If the refcount falls to 0, the part should
  1109. //                release the GetODPart() part reference.
  1110. //
  1111. // Warning:        If the part releases any other object when the refcount falls to
  1112. //                zero, it will need to override the Acquire method so
  1113. //                that the object can be referenced again if the parts refcount
  1114. //                should be incremented before it is deleted.
  1115. //------------------------------------------------------------------------------
  1116.  
  1117. void DrawEditor::Release( Environment* ev )
  1118. {
  1119.     SOM_Trace("DrawEditor","Release");
  1120.  
  1121.     ODPart* tPart = this->GetODPart();
  1122.     
  1123.     if (tPart->GetRefCount(ev) == 0)
  1124.         this->GetDraft(ev)->ReleasePart(ev, tPart);
  1125. }
  1126.  
  1127. //------------------------------------------------------------------------------
  1128. // Method:        ReleaseAll
  1129. // Origin:        ODPart
  1130. //
  1131. // Description:    This method is called just prior to the part being
  1132. //                deleted by the Draft. The part must release all
  1133. //                references to all refcounted objects it has stored
  1134. //                internally; not doing so, will cause an "invalid ref
  1135. //                count" exception/error.
  1136. //------------------------------------------------------------------------------
  1137.  
  1138. void DrawEditor::ReleaseAll( Environment* ev )
  1139. {
  1140.     SOM_Trace("DrawEditor","ReleaseAll");
  1141.  
  1142.     TRY
  1143.  
  1144.         // Profiling
  1145.         #ifdef qProfileDrawEditor
  1146.         char x[255] = "/pDrawEditorProfile";
  1147.         OSErr err = ::ProfilerDump((StringPtr)"\pServo:DrawEditorProfile");
  1148.         ::ProfilerTerm();
  1149.         #endif
  1150.         
  1151.         // Check to see if we have any promises on the clipboard
  1152.         // if so, resolve them, per recipe.
  1153.         ::ResolveClipboardPromises(ev, this->GetSession(ev));
  1154.         
  1155.         // Release our global floating window proc
  1156.         if (gGlobals->fFloatWindowProc)
  1157.             ::ReleaseResource(gGlobals->fFloatWindowProc);
  1158.         
  1159.         // Release our display frames and delete their proxy
  1160.         if (fDisplayFrameProxies)
  1161.         {
  1162.             COrdListIterator fiter(fDisplayFrameProxies);
  1163.             for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  1164.                     fiter.IsNotComplete();
  1165.                     frameProxy=(CDisplayFrameProxy*)fiter.Next())
  1166.             {
  1167.                 if (frameProxy->IsFrameInMemory())
  1168.                 {
  1169.                     ODFrame* frame = frameProxy->GetFrame(ev);
  1170.                     ODReleaseObject(ev,frame);
  1171.                 }
  1172.                 delete frameProxy;
  1173.             }
  1174.         }
  1175.         
  1176.         // 
  1177.         if ( fDisplayFrameProxies )
  1178.         {
  1179.             ODDeleteObject(fDisplayFrameProxies);
  1180.             fDisplayFrameProxies = kODNULL;
  1181.         }
  1182.  
  1183.         
  1184.         if (fPendingPublish && fPendingPublish->CanDelete())
  1185.             delete fPendingPublish;
  1186.         
  1187.         fPendingPublish = NULL;
  1188.         
  1189.         if (fPendingDragPublish && fPendingDragPublish->CanDelete())
  1190.             delete fPendingDragPublish;
  1191.     
  1192.         fPendingDragPublish = NULL;
  1193.         
  1194.         // Delete publishers
  1195.         if (fPublishLinks)
  1196.         {
  1197.             CPublishLink* link;
  1198.             while ((link = (CPublishLink*)fPublishLinks->RemoveFirst()) != NULL)
  1199.             {
  1200.                 delete link;
  1201.             }        
  1202.         }
  1203.         
  1204.         // Delete subscribers
  1205.         if (fSubscribeLinks)
  1206.         {
  1207.             CSubscribeLink* link;
  1208.             while ((link = (CSubscribeLink*)fSubscribeLinks->RemoveFirst()) != NULL)
  1209.             {
  1210.                 delete link;
  1211.             }        
  1212.         }
  1213.         
  1214.         // Destroy our content shapes
  1215.         if (fShapeList)
  1216.         {
  1217.             COrdListIterator iter(fShapeList);
  1218.             for ( CShape* shape = (CShape*)iter.First();
  1219.                  iter.IsNotComplete();
  1220.                  shape = (CShape*)iter.Next() )
  1221.             {
  1222.                 delete shape;
  1223.             }
  1224.         }
  1225.                 
  1226.         
  1227.         // Release the active border shape
  1228.         if (fActiveBorderShape)
  1229.         {
  1230.             ODReleaseObject(ev,fActiveBorderShape);
  1231.         }
  1232.         
  1233.         // If the last part instance using the globals is released,
  1234.         // we need to NULL out the globals.
  1235.         
  1236.         if ( --gGlobalsUsageCount == 0 )
  1237.         {
  1238.             // Release the menu bar
  1239.             ODReleaseObject(ev,gGlobals->fMenuBar);
  1240.             
  1241.             // the FocusSet is not shared so  delet it
  1242.             if ( gGlobals->fUIFocusSet )
  1243.             {
  1244.                 ODDeleteObject(gGlobals->fUIFocusSet);
  1245.                 gGlobals->fUIFocusSet = kODNULL;
  1246.             }
  1247.         
  1248.             // Release the thumbnail (PICT) resource.
  1249.             if ( gGlobals->fThumbnail )
  1250.             {
  1251.                 ReleaseResource(gGlobals->fThumbnail);
  1252.                 gGlobals->fThumbnail = kODNULL;
  1253.             }
  1254.         
  1255.             // Also, getting rid of our palettes is good idea also.
  1256.             if (gGlobals->fColorPalette)
  1257.             {
  1258.                 ODDeleteObject(gGlobals->fColorPalette);
  1259.                 gGlobals->fColorPalette = kODNULL;
  1260.             }
  1261.             if (gGlobals->fToolPalette)
  1262.             {
  1263.                 ODDeleteObject(gGlobals->fToolPalette);
  1264.                 gGlobals->fToolPalette = kODNULL;
  1265.             }
  1266.         }
  1267.         
  1268.     CATCH_ALL
  1269.         // If something goes wrong while we are cleaning up, we must
  1270.         // let the Draft know because there may be some refcounted objects
  1271.         // which did not get released. Not to mention, possible memory
  1272.         // leaks.
  1273.         RERAISE;            
  1274.     ENDTRY
  1275. }
  1276.  
  1277. //------------------------------------------------------------------------------
  1278. // Method:        Purge
  1279. // Origin:        ODPart
  1280. //
  1281. // Description:    This method is called when the OpenDoc requires more
  1282. //                memory for allocating objects and just before a part
  1283. //                is deleted. The part should free up as much memory as
  1284. //                it can.
  1285. //
  1286. //                The part determines which views are being "used" in
  1287. //                its display frames. The resources for the unused view
  1288. //                types are then purged.
  1289. //------------------------------------------------------------------------------
  1290.  
  1291. ODSize DrawEditor::Purge( Environment*    ev,
  1292.                           ODSize        /*size*/ )
  1293. {
  1294.     SOM_Trace("DrawEditor","Purge");
  1295.  
  1296.     // Purge is called during the creation of stationery. However,
  1297.     // we have not created our internal display frames list, so 
  1298.     // trying to iterate over it would be futile.
  1299.     if ( !fDisplayFrameProxies ) return 0;
  1300.     
  1301.     ODSize         bytesFreed        = 0;
  1302.     ODBoolean    usingGlobals  = kODFalse;
  1303.     
  1304.     // Iterate over the frames we are displayed through and determine which
  1305.     // view types are currently in use.
  1306.     
  1307.     COrdListIterator fiter(fDisplayFrameProxies);
  1308.     for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  1309.             fiter.IsNotComplete();
  1310.             frameProxy=(CDisplayFrameProxy*)fiter.Next())
  1311.     {
  1312.         if (frameProxy->IsFrameInMemory())
  1313.         {
  1314.             ODFrame* frame = frameProxy->GetFrame(ev);
  1315.             ODTypeToken    frameView    = frame->GetViewType(ev);
  1316.             
  1317.             if ( frameView == gGlobals->fThumbnailView )
  1318.                 usingGlobals = kODTrue;
  1319.         }
  1320.     }
  1321.     
  1322.     // Based on the usage of the supported view types, free up as much
  1323.     // memory as possible.
  1324.     
  1325.     if ( !usingGlobals && (gGlobals->fThumbnail != kODNULL) )
  1326.     {
  1327.         bytesFreed += (ODSize) GetHandleSize(gGlobals->fThumbnail);
  1328.         ::ODDeletePicture((PicHandle)gGlobals->fThumbnail);
  1329.         gGlobals->fThumbnail = kODNULL;
  1330.     }
  1331.     
  1332.     return bytesFreed;
  1333. }
  1334.  
  1335. //------------------------------------------------------------------------------
  1336. // Method:        InternalizeStateInfo
  1337. // Origin:        DrawEditor
  1338. //
  1339. // Description:    This method could be used to read in settings
  1340. //                information for the part. This would be information
  1341. //                related to the workings of the part editor, not the
  1342. //                content.
  1343. //
  1344. // Note:        The function StorageUnitGetValue simplifies the use of
  1345. //                ODByteArrary, which is required by the StorageUnit
  1346. //                interface. Look in StorUtil.h/cpp for an example of
  1347. //                using the ODByteArray struct.
  1348. //------------------------------------------------------------------------------
  1349.  
  1350. void DrawEditor::InternalizeStateInfo( Environment*        ev,
  1351.                                        ODStorageUnit*    storageUnit )
  1352. {
  1353.     SOM_Trace("DrawEditor","InternalizeStateInfo");
  1354.  
  1355.     // Internalize the part's display frame proxy list.
  1356.  
  1357.     ODULong                size;
  1358.     
  1359.     if ( storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
  1360.     {
  1361.         storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  1362.                                     kODWeakStorageUnitRefs, 0, kODPosUndefined);
  1363.                                     
  1364.         // Read test value
  1365.         ODUShort testValue = 0;
  1366.         StorageUnitGetValue(storageUnit, ev, sizeof(ODUShort), &testValue);
  1367.     
  1368.         size = storageUnit->GetSize(ev);
  1369.         storageUnit->SetOffset(ev, 0);    
  1370.     
  1371.         for ( ODULong offset = 0; offset < size; offset += sizeof(ODStorageUnitRef) )
  1372.         {    
  1373.             CDisplayFrameProxy* tProxy = kODNULL;
  1374.             ODVolatile(tProxy);
  1375.             TRY
  1376.                 CDisplayFrameProxy* tProxy = new CDisplayFrameProxy();
  1377.                 tProxy->InitializeDisplayFrameProxy(ev, this);
  1378.                 
  1379.                 tProxy->Read(ev, storageUnit, kODNULL);
  1380.                 fDisplayFrameProxies->AddLast(tProxy);
  1381.             CATCH_ALL
  1382.                 if (tProxy)
  1383.                 {
  1384.                     delete tProxy;
  1385.                 }
  1386.             ENDTRY
  1387.         }
  1388.     }
  1389. }
  1390.  
  1391. //------------------------------------------------------------------------------
  1392. // Method:        InternalizeContent
  1393. // Origin:        DrawEditor
  1394. //
  1395. // Description:    This method is called during interalization of the
  1396. //                part. Document state info, content of part, as well as any link info
  1397. //                 is read in. The work is all done by the CDrawContent object.
  1398. //------------------------------------------------------------------------------
  1399.  
  1400. void DrawEditor::InternalizeContent( Environment*        ev,
  1401.                                      ODStorageUnit*        storageUnit )
  1402. {
  1403.     SOM_Trace("DrawEditor","InternalizeContent");
  1404.     
  1405.     // focus to our content property.
  1406.     TRY
  1407.         if ( storageUnit->Exists(ev, kODPropContents, kDrawEditorKind, 0) )
  1408.         {
  1409.             storageUnit->Focus(ev, kODPropContents, kODPosUndefined,
  1410.                                     kDrawEditorKind, 0, kODPosUndefined);
  1411.         
  1412.             fPartContent->Internalize(ev, storageUnit, kODNULL);
  1413.         }
  1414.     CATCH_ALL
  1415.         ODSetSOMException(ev, ErrorCode());
  1416.     ENDTRY
  1417.  
  1418.  
  1419. }
  1420.  
  1421. //------------------------------------------------------------------------------
  1422. // Method:        ClonePartInfo
  1423. // Origin:        ODPart
  1424. //
  1425. // Description:    When a frame is being cloned by the Draft, it will ask the owner
  1426. //                (part) to clone its info annotation on the frame.
  1427. //
  1428. //                The part uses a C++ helper class to encapsulate the information
  1429. //                we store with each frame, so we let it clone itself to the
  1430. //                storage unit view.
  1431. //------------------------------------------------------------------------------
  1432.  
  1433. void DrawEditor::ClonePartInfo( Environment*        ev,
  1434.                                 ODDraftKey            key,
  1435.                                   ODInfoType            partInfo,
  1436.                                 ODStorageUnitView*    storageUnitView,
  1437.                                 ODFrame*            scopeFrame )
  1438. {
  1439.     SOM_Trace("ClonePartInfo","ClonePartInfo");
  1440.  
  1441.     // Tell our frame info class to write itself out into the pre-
  1442.     // focused storage unit.
  1443.     ((CFrameInfo*) partInfo)->CloneInto(ev, key, storageUnitView, scopeFrame);
  1444. }
  1445.  
  1446.  
  1447. //------------------------------------------------------------------------------
  1448. // Method:        CloneInto
  1449. // Origin:        ODPart
  1450. //
  1451. // Description:    This method is called during cloning, typically
  1452. //                inside of Data Interchange operations. The part should
  1453. //                write out the current state and contents.
  1454. //------------------------------------------------------------------------------
  1455.  
  1456. void DrawEditor::CloneInto( Environment*        ev,
  1457.                             ODDraftKey            key,
  1458.                             ODStorageUnit*        destinationSU,
  1459.                             ODFrame*            scopeFrame )
  1460. {
  1461.     SOM_Trace("DrawEditor","CloneInto");
  1462.     
  1463.     // We must first verify that we've never written to this storage unit.
  1464.     // If we have, we should do nothing, otherwise we need to write out
  1465.     // the current state of the part content.
  1466.     
  1467.     if ( destinationSU->Exists(ev, kODPropContents, kDrawEditorKind, 0) == kODFalse )
  1468.     {
  1469.         
  1470.         // This is where, we should check for the existence of the kODPropContentFrame property
  1471.         // and write a promise if it's there.  When doing so, we will need to read any kODPropCloneKind's kODCloneKind value
  1472.         // and use that in our cloneKind record.  Otherwise the promise, when fulfilled may call BeginClone with the wrong
  1473.         // cloneKind (ie one different from the containing part which called BeginClone before cloning this as a single
  1474.         // embedded frame.
  1475.         
  1476.         // based
  1477.         // Add the properties we need to successfully externalize
  1478.         // ourselves into the destination storage unit.
  1479.         this->CheckAndAddProperties(ev, destinationSU);
  1480.                 
  1481.         // Assemble the bits of info necessary for the clone operation.
  1482.         // These are the: key from the clone begun by OD, the source draft,
  1483.         // the scope frame, and the clone kind.
  1484.         CCloneInfo info(key, this->GetDraft(ev), scopeFrame, kODCloneCopy);
  1485.         
  1486.         // Write out the part's state information.
  1487.         this->ExternalizeStateInfo(ev, destinationSU, &info);
  1488.         
  1489.         // Write out the part's content.
  1490.         this->ExternalizeContent(ev, destinationSU, &info);
  1491.     }
  1492. }
  1493.  
  1494. //------------------------------------------------------------------------------
  1495. // Method:        Externalize
  1496. // Origin:        ODPart
  1497. //
  1498. // Description:    Write out our persistent state if changes have
  1499. //                occurred and if our storage is writeable. The part
  1500. //                must call its parent class behavior because one or
  1501. //                more of our parent classes contains implementation.
  1502. //------------------------------------------------------------------------------
  1503.  
  1504. void DrawEditor::Externalize( Environment* ev )
  1505. {
  1506.     SOM_Trace("DrawEditor","Externalize");
  1507.  
  1508.     if ( fDirty && !IsReadOnly())
  1509.     {
  1510.         TRY
  1511.         
  1512.             // Get our storage unit.
  1513.             ODStorageUnit* storageUnit = this->GetODPart()->GetStorageUnit(ev);
  1514.     
  1515.             // Verify that the storage unit has the appropriate properties
  1516.             // and values to allow us to run. If not, add them.
  1517.             this->CheckAndAddProperties(ev, storageUnit);
  1518.         
  1519.             // Verify that there are no "bogus" values in the Content
  1520.             // property.
  1521.             this->CleanseContentProperty(ev, storageUnit);
  1522.         
  1523.             // Write out the part's state information.
  1524.             this->ExternalizeStateInfo(ev, storageUnit, kODNULL);
  1525.                 
  1526.             // Write out the part's content.
  1527.             this->ExternalizeContent(ev, storageUnit, kODNULL);
  1528.  
  1529.         CATCH_ALL
  1530.             // Alert the user of the problem.
  1531.             this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrExternalizeFailed);
  1532.             // Change the exception value, so the DocShell doesn't display an
  1533.             // error dialog.
  1534.             SetErrorCode(kODErrAlreadyNotified);
  1535.             // Alert the caller.
  1536.             RERAISE;
  1537.         ENDTRY
  1538.         
  1539.         // Flag our part as no longer being dirty.
  1540.         fDirty = kODFalse;
  1541.     }
  1542. }
  1543.  
  1544. //------------------------------------------------------------------------------
  1545. // Method:        ExternalizeStateInfo
  1546. // Origin:        DrawEditor
  1547. // Description:    This method is called during externalization pr cloning of the
  1548. //                part. The current "state" of the editor should be
  1549. //                written out. This "state" information may be lost
  1550. //                during Data Interchange operations, so the part needs
  1551. //                to recover gracefully if information is missing or
  1552. //                incomplete.
  1553. //
  1554. // Note:        The function StorageUnitSetValue is a macro which
  1555. //                simplifies the use of ODByteArrary, which is required
  1556. //                the StorageUnit interface. Look in StorUtil.h/cpp for
  1557. //                an example of using the ODByteArray struct.
  1558. //------------------------------------------------------------------------------
  1559.  
  1560. void DrawEditor::ExternalizeStateInfo( Environment*        ev,
  1561.                                        ODStorageUnit*    storageUnit,
  1562.                                        CCloneInfo*        info)
  1563. {
  1564.     SOM_Trace("DrawEditor","ExternalizeStateInfo");
  1565.     
  1566.     // Externalize the part's display frame list.
  1567.  
  1568.     storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  1569.                                 kODWeakStorageUnitRefs, 0, kODPosUndefined);
  1570.     
  1571.     // Persistent object references are stored in a side table, rather than
  1572.     // in the property/value stream. Thus, deleting the contents of a value
  1573.     // will not "delete" the references previously written to that value. To
  1574.     // completely "delete" all references written to the value, we must
  1575.     // remove the value and add it back.
  1576.     storageUnit->Remove(ev);
  1577.     storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1578.  
  1579.     COrdListIterator fiter2(fDisplayFrameProxies);
  1580.     for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter2.First();
  1581.             fiter2.IsNotComplete();
  1582.             frameProxy = (CDisplayFrameProxy*)fiter2.Next())
  1583.     {
  1584.         TRY
  1585.             // Only write frame proxies if they are the main presentation
  1586.             // since our palettes are not persistent. This test does not
  1587.             // take into account the possiblity of a proxy being added 
  1588.             // by ID that should be saved. Currently DrawEditor doesn't allow
  1589.             // that to happen.
  1590.             if (frameProxy->IsFrameInMemory())
  1591.             {
  1592.                 ODFrame* tFrame = frameProxy->GetFrame(ev);
  1593.                 if (tFrame->GetPresentation(ev)==gGlobals->fMainPresentation)
  1594.                 {
  1595.                     frameProxy->Write(ev, storageUnit, info);
  1596.                 }
  1597.             }
  1598.          CATCH_ALL
  1599.              // Consume the exception
  1600.              #ifdef ODDebug
  1601.                  DebugStr("\pFailure externalizing state info.");
  1602.              #endif
  1603.          ENDTRY
  1604.     }
  1605. }
  1606.  
  1607. //------------------------------------------------------------------------------
  1608. // Method:        ExternalizeContent
  1609. // Origin:        DrawEditor
  1610. //
  1611. // Description:    This method is called during exteralization of the
  1612. //                part. The content of the part should be written out.
  1613. //
  1614. // Note: This method adds an additional parameter unlike other parts derived
  1615. // from DrawEditor. The cloneInfo parameter is used to communicate clone info
  1616. // passed into the CloneInto method so that the editor may clone embedded its
  1617. // embedded frames to the given storage.
  1618. //------------------------------------------------------------------------------
  1619.  
  1620. void DrawEditor::ExternalizeContent( Environment*        ev,
  1621.                                      ODStorageUnit*        storageUnit,
  1622.                                      CCloneInfo*        cloneInfo )
  1623. {
  1624.     SOM_Trace("DrawEditor","ExternalizeContent");
  1625.  
  1626.     TRY
  1627.         // focus to our content property.
  1628.         if ( storageUnit->Exists(ev, kODPropContents, kDrawEditorKind, 0) )
  1629.         {
  1630.             storageUnit->Focus(ev, kODPropContents, kODPosUndefined,
  1631.                                     kDrawEditorKind, 0, kODPosUndefined);
  1632.     
  1633.             fPartContent->Externalize(ev, storageUnit, cloneInfo);
  1634.         }
  1635.         
  1636.     CATCH_ALL
  1637.         ODSetSOMException(ev, ErrorCode());
  1638.     ENDTRY
  1639.     
  1640.     
  1641. }
  1642.  
  1643. //------------------------------------------------------------------------------
  1644. // Method:        FulfillPromise
  1645. // Origin:        DrawEditor
  1646. //
  1647. // Description:    This method is called by OpenDoc when a promise of data ( that 
  1648. // we made ) needs to be resolved. The storage unit we get passed should be 
  1649. // focused to a proeprty and value containing our original byte array that we
  1650. // promised earlier. We need to read that byte array and use it to write the
  1651. // actual data that was promisedf into that SAME property and value.
  1652. //------------------------------------------------------------------------------
  1653.  
  1654. void DrawEditor::FulfillPromise(Environment* ev, ODStorageUnitView* promiseSUView)
  1655. {
  1656.     CPromise* promise = kODNULL;
  1657.     TRY
  1658.         StorageUnitViewGetValue(promiseSUView, ev, sizeof(CPromise*), &promise);
  1659.         THROW_IF_NULL(promise);
  1660.         
  1661.         // Reset the storage unit view so the value we just read will get overwritten.
  1662.         promiseSUView->SetOffset(ev, 0);
  1663.         
  1664.         // We assume that the promise that was returned by the get value call wwas good.
  1665.         promise->FulfillPromise(ev, promiseSUView);
  1666.     
  1667.     CATCH_ALL
  1668.         ODSetSOMException(ev, ErrorCode());
  1669.     ENDTRY
  1670.     
  1671.     // The promise could be null if we've thrown above.
  1672.     if (promise)
  1673.     {
  1674.         if (promise->OKToDelete())
  1675.         {
  1676.             delete promise;
  1677.         }
  1678.     }
  1679. }
  1680.  
  1681.  
  1682. //------------------------------------------------------------------------------
  1683. // Method:        CleanseContentProperty
  1684. // Origin:        DrawEditor
  1685. //
  1686. // Description:    This method is called during exteralization of the
  1687. //                part. The part should remove any value in the content property
  1688. //                that it cannot "accurately" write to.
  1689. //------------------------------------------------------------------------------
  1690.  
  1691. void DrawEditor::CleanseContentProperty( Environment*        ev,
  1692.                                          ODStorageUnit*        storageUnit )
  1693. {
  1694.     SOM_Trace("DrawEditor","CleanseContentProperty");
  1695.  
  1696.     ODULong numValues;
  1697.     ODULong index;
  1698.     
  1699.     storageUnit->Focus(ev, kODPropContents, kODPosUndefined, 
  1700.                             kODNULL, 0, kODPosAll);
  1701.     
  1702.     numValues = storageUnit->CountValues(ev);
  1703.     
  1704.     for (index = numValues; index >= 1; index--)
  1705.     {
  1706.         // Index from 1 to n through the values.
  1707.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined, 
  1708.                                 kODNULL, index, kODPosUndefined);
  1709.                                 
  1710.         // Get the ISO type name for the value. The temp object
  1711.         // will automatically delete the returned value when this
  1712.         // scope is exited.
  1713.         TempODValueType value = storageUnit->GetType(ev);
  1714.         
  1715.         // If the value type is not one we support, remove it.
  1716.         if ( ODISOStrCompare(value, kDrawEditorKind) != 0 )
  1717.             storageUnit->Remove(ev);
  1718.     }
  1719. }
  1720.  
  1721. //------------------------------------------------------------------------------
  1722. // Method:        CheckAndAddProperties
  1723. // Origin:        DrawEditor
  1724. //
  1725. // Description:    This method is called during the creation of
  1726. //                stationery, to prepare a storage unit, and during
  1727. //                externalization, to verify that all the properties we
  1728. //                need are present.
  1729. //
  1730. //                The part adds the default content property, a
  1731. //                preferred editor property (to aid in part binding), 
  1732. //                and a default name for the part.
  1733. //
  1734. // Note:        The function StorageUnitSetValue is a macro which
  1735. //                simplifies the use of ODByteArrary, which is required
  1736. //                the StorageUnit interface. Look in StorUtil.h/cpp for
  1737. //                an example of using the ODByteArray struct.
  1738. //------------------------------------------------------------------------------
  1739.  
  1740. void DrawEditor::CheckAndAddProperties( Environment*    ev,
  1741.                                         ODStorageUnit*    storageUnit )
  1742. {
  1743.     SOM_Trace("DrawEditor","CheckAndAddProperties");
  1744.     
  1745.     // Create our content property and preferred content property kind.
  1746.  
  1747.     if ( !storageUnit->Exists(ev, kODPropContents, kODNULL, 0) )
  1748.         storageUnit->AddProperty(ev, kODPropContents);
  1749.     if ( !storageUnit->Exists(ev, kODPropContents, kDrawEditorKind, 0) )
  1750.     {    
  1751.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosAll);
  1752.         storageUnit->AddValue(ev, kDrawEditorKind);
  1753.     }
  1754.  
  1755.     // Since we are setting up the preferred kind property, we just write
  1756.     // out our default "kind" for the editor. We can write out the user
  1757.     // chosen kind in the ExternalizeStateInfo method.
  1758.  
  1759.     if ( !storageUnit->Exists(ev, kODPropPreferredKind, kODISOStr, 0) )
  1760.     {
  1761.         TRY
  1762.             ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, kDrawEditorKind);
  1763.         CATCH_ALL
  1764.             // Remove the property and value if something went wrong.
  1765.             ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  1766.         ENDTRY
  1767.     }
  1768.     
  1769.     // Add our display frame list.
  1770.     
  1771.     if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODNULL, 0) )
  1772.         storageUnit->AddProperty(ev, kODPropDisplayFrames);
  1773.     if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
  1774.     {
  1775.         storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined, kODNULL, 0, kODPosAll);
  1776.         storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1777.     }
  1778. }
  1779.  
  1780. //------------------------------------------------------------------------------
  1781. // Method:        SetDirty
  1782. // Origin:        DrawEditor
  1783. //
  1784. // Description:    This method is called by the part when the content or
  1785. //                state of the part has been modified by the user and
  1786. //                the "Save" menu item should be enabled.
  1787. //------------------------------------------------------------------------------
  1788.  
  1789. void DrawEditor::SetDirty( Environment*    ev )
  1790. {
  1791.     SOM_Trace("DrawEditor","SetDirty");
  1792.  
  1793.     // There is no need to repeatedly tell the draft we have changed;
  1794.     // once is sufficient.
  1795.     if ( !fDirty && !fReadOnlyStorage )
  1796.     {
  1797.         fDirty = kODTrue;
  1798.         this->GetDraft(ev)->SetChangedFromPrev(ev);
  1799.     }
  1800. }
  1801.  
  1802.  
  1803. //------------------------------------------------------------------------------
  1804. // Method:        ExternalizeKinds
  1805. // Origin:        ODPart
  1806. //
  1807. // Description:    This method is called when the user wants to save the document
  1808. //                with multiple representations of the data. This is especially
  1809. //                useful for increasing the portability of documents
  1810. //                cross-platform.
  1811. //
  1812. //                A part should verify each kind is valid, that it exists in
  1813. //                the content property in the correct order, and write the data.
  1814. //------------------------------------------------------------------------------
  1815.  
  1816. void DrawEditor::ExternalizeKinds(Environment* ev, ODTypeList* kindset)
  1817. {
  1818.     if ( !fReadOnlyStorage )
  1819.     {
  1820.         ODBoolean preferredKindWritten = kODFalse;
  1821.         
  1822.         // Get our storage unit.
  1823.         ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  1824.         
  1825.         // Verify that the storage unit has the appropriate properties
  1826.         // and values to allow us to run. If not, add them.
  1827.         this->CheckAndAddProperties(ev, storageUnit);
  1828.     
  1829.         // Verify that there are no "bogus" values in the Content
  1830.         // property.
  1831.         this->CleanseContentProperty(ev, storageUnit);
  1832.     
  1833.         // Iterate over the kindset and write out the content types
  1834.         // that we support.
  1835.         TempODTypeListIterator tliter(ev, kindset);
  1836.         for ( ODType kind = tliter.First(); tliter.IsNotComplete();
  1837.                 kind = tliter.Next() )
  1838.         {
  1839.             // Check to see if this is a kind we support. If so, write it.
  1840.             if ( ODISOStrCompare(kind, kDrawEditorKind) == 0 )
  1841.             {
  1842.                 // Write out the part's content.
  1843.                 this->ExternalizeContent(ev, storageUnit, kODNULL);
  1844.                 // This is our preferrend kind so we don't need to write it again.
  1845.                 // Part editors with more than one kind need to test each kind
  1846.                 // against the preferred kind to make sure it's been written.
  1847.                 preferredKindWritten = kODTrue;
  1848.             }
  1849.         }
  1850.     
  1851.         // Write out the part's state information.
  1852.         this->ExternalizeStateInfo(ev, storageUnit, kODNULL);
  1853.  
  1854.         // Even if the kind set contains no types we support, we must at least
  1855.         // write out our current "preferred" kind.
  1856.         if ( preferredKindWritten == kODFalse )
  1857.         {
  1858.             // Write out the part's preferred content kind, which, for DrawEditor,
  1859.             // is the only kind.
  1860.             this->ExternalizeContent(ev, storageUnit, kODNULL);
  1861.         }
  1862.     }
  1863. }
  1864.  
  1865. //------------------------------------------------------------------------------
  1866. // Method:        ChangeKind
  1867. // Origin:        ODPart
  1868. //
  1869. // Description:    This method is called when the changes the part's primary kind
  1870. //                and/or when the part editor is switched via the Info dialog.
  1871. //
  1872. //                The editor should record the new "preferred" kind and change the
  1873. //                UI, if necessary, to allow editing of that kind. Don't write the
  1874. //                properties/values/data until the Externalize is called.
  1875. //------------------------------------------------------------------------------
  1876.  
  1877. void DrawEditor::ChangeKind(Environment* ev, ODType kind)
  1878. {
  1879.     // DrawEditor only has one kind, but we need to make sure the "Preferred Kind"
  1880.     // property has the correct value.
  1881.     if ( ODISOStrCompare(kind, kDrawEditorKind) == 0 )
  1882.     {
  1883.         // Get our storage unit.
  1884.         ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
  1885.         
  1886.         TRY
  1887.             // Write out the users preferred kind.
  1888.             ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, kDrawEditorKind);
  1889.             
  1890.             // Changing our kind dirties our content.
  1891.             this->SetDirty(ev);
  1892.             
  1893.             // Immediately externalize ourselves in the "new" format.
  1894.             this->Externalize(ev);
  1895.         CATCH_ALL
  1896.             // Remove the property and value if something went wrong.
  1897.             ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  1898.         ENDTRY
  1899.     }
  1900.     else
  1901.         THROW(kODErrInvalidValueType);
  1902. }
  1903.  
  1904.  
  1905. //------------------------------------------------------------------------------
  1906. // Method:        ReadPartInfo
  1907. // Origin:        ODPart
  1908. //
  1909. // Description:    When a frame is being internalized by the Draft, it
  1910. //                will ask the owner (part) to read in its info
  1911. //                annotation on the frame.
  1912. //
  1913. //                The part info class knows how to internalize itself
  1914. //                from a storage unit view, so we just call
  1915. //                CFrameInfo::InitFromStorage.
  1916. //------------------------------------------------------------------------------
  1917.  
  1918. ODInfoType DrawEditor::ReadPartInfo( Environment*        ev,
  1919.                                      ODFrame*            frame,
  1920.                                      ODStorageUnitView*    storageUnitView )
  1921. {
  1922.     SOM_Trace("DrawEditor","ReadPartInfo");
  1923.  
  1924.     CFrameInfo* frameInfo = kODNULL;
  1925.         
  1926.     TRY
  1927.         frameInfo = new CFrameInfo;
  1928.         frameInfo->InitFromStorage(ev, storageUnitView);
  1929.  
  1930.         // Hook the runtime display frame synchonization mechanism back up.
  1931.         if ( frameInfo->HasSourceFrame() )
  1932.         {
  1933.             CFrameInfo* sourceFrameInfo = 
  1934.                 (CFrameInfo*) frameInfo->GetSourceFrame()->GetPartInfo(ev);
  1935.  
  1936.             sourceFrameInfo->AttachFrame(ev, frame);
  1937.         }
  1938.         
  1939.     CATCH_ALL
  1940.     ENDTRY
  1941.     
  1942.     return (ODInfoType)frameInfo;
  1943. }
  1944.  
  1945. //------------------------------------------------------------------------------
  1946. // Method:        WritePartInfo
  1947. // Origin:        ODPart
  1948. //
  1949. // Description:    When a frame is being externalized by the Draft, it
  1950. //                will ask the owner (part) to write out its info
  1951. //                annotation on the frame.
  1952. //
  1953. //                The part info class knows how to externalize itself
  1954. //                to a storage unit view, so we just call Externalize.
  1955. //------------------------------------------------------------------------------
  1956.  
  1957. void DrawEditor::WritePartInfo( Environment*        ev,
  1958.                                   ODInfoType            partInfo,
  1959.                                 ODStorageUnitView*    storageUnitView )
  1960. {
  1961.     SOM_Trace("DrawEditor","WritePartInfo");
  1962.  
  1963.     // Tell our frame info class to write itself out into the pre-
  1964.     // focused storage unit.
  1965.     ((CFrameInfo*) partInfo)->Externalize(ev, storageUnitView);
  1966. }
  1967.  
  1968. //------------------------------------------------------------------------------
  1969. // Method:        DisplayFrameAdded
  1970. // Origin:        ODPart
  1971. //
  1972. // Description:    This method is called in response to a frame being
  1973. //                created for our part.
  1974. //
  1975. //                The part records the existence of a new display frame
  1976. //                in its internal display frame list, as well as,
  1977. //                verify that the frame is "set up" correctly (i.e.,
  1978. //                valid viewType). The part also creates and stores its
  1979. //                "frame info" class in the new frame. 
  1980. //------------------------------------------------------------------------------
  1981.  
  1982. void DrawEditor::DisplayFrameAdded( Environment*    ev,
  1983.                                        ODFrame*        frame )
  1984. {
  1985.     SOM_Trace("DrawEditor","DisplayFrameAdded");
  1986.     
  1987.     ODBoolean isMainPresentation = frame->GetPresentation(ev)==gGlobals->fMainPresentation;
  1988.  
  1989.     // If we are being embedded into another part, the presentation field
  1990.     // will be NULL, so we need to set it something meaningful.
  1991.     // The view field may also be null, if so, we prefer to be displayed
  1992.     // in a frame view.
  1993.  
  1994.     // We shouldn't be given a frame with an foreign presentation
  1995.     // If we do get one, set it to our main presentation.
  1996.     ODTypeToken tPresentation = frame->GetPresentation(ev);
  1997.     if ( tPresentation != gGlobals->fMainPresentation &&
  1998.         tPresentation != gGlobals->fColorPalette->GetPresentation() &&
  1999.         tPresentation != gGlobals->fToolPalette->GetPresentation()  )
  2000.     {
  2001.         frame->SetPresentation(ev, gGlobals->fMainPresentation);
  2002.         isMainPresentation = kODTrue;
  2003.     }
  2004.     
  2005.     
  2006.     // Only frame with gGlobals->fMainPresentation are droppable.
  2007.     if (isMainPresentation)
  2008.     {
  2009.             frame->SetDroppable(ev, kODTrue);
  2010.     
  2011.         // Create frame proxies for any shapes already added when this
  2012.         // frame was added
  2013.         COrdListIterator iter(fShapeList);
  2014.         if (fShapeList)
  2015.             for ( CShape* shape = (CShape*)iter.First();
  2016.                  iter.IsNotComplete();
  2017.                  shape = (CShape*)iter.Next() )
  2018.             {
  2019.                 shape->DisplayFrameAdded(ev, frame);
  2020.             }
  2021.     }
  2022.  
  2023.     
  2024.     // If there is no view type then default it to gGlobals->fFrameView
  2025.     if ( frame->GetViewType(ev) == kODNullTypeToken )
  2026.         frame->SetViewType(ev, gGlobals->fFrameView);
  2027.             
  2028.     // Hang our "state" info off of the new display frame. We use
  2029.     // the CFrameInfo object for activation, updating, and window
  2030.     // maintenance.
  2031.  
  2032.     CFrameInfo* frameInfo = new CFrameInfo;
  2033.     frame->SetPartInfo(ev, (ODInfoType)frameInfo);
  2034.     
  2035.     // Create a proxy for this frame and add it to our list    
  2036.     CDisplayFrameProxy* tProxy = new CDisplayFrameProxy();
  2037.     tProxy->InitializeDisplayFrameProxy(ev, this, kODNULLID, frame);
  2038.     fDisplayFrameProxies->AddLast(tProxy);
  2039.  
  2040.     // Since we maintain a persistent list of weak references to our
  2041.     // persistent display frames, having one added to the part dirties it.
  2042.     if (isMainPresentation)
  2043.         this->SetDirty(ev);
  2044. }
  2045.  
  2046.  
  2047. //------------------------------------------------------------------------------
  2048. // Method:        DisplayFrameConnected
  2049. // Origin:        ODPart
  2050. //
  2051. // Description:    This method is called when one of our display frames,
  2052. //                previously written out, is internalized. This method
  2053. //                is called instead of DisplayFrameAdded because a "new"
  2054. //                frame is not being created; an existing one is being
  2055. //                reconstituted.
  2056. //------------------------------------------------------------------------------
  2057.  
  2058. void DrawEditor::DisplayFrameConnected( Environment*    ev,
  2059.                                         ODFrame*        frame )
  2060. {
  2061.     SOM_Trace("DrawEditor","DisplayFrameConnected");
  2062.  
  2063.     ODBoolean isMainPresentation = frame->GetPresentation(ev)==gGlobals->fMainPresentation;
  2064.     
  2065.     // We shouldn't be given a frame with an foreign presentation
  2066.     // If we do get one, set it to our main presentation.
  2067.     ODTypeToken tPresentation = frame->GetPresentation(ev);
  2068.     if ( tPresentation != gGlobals->fMainPresentation &&
  2069.         tPresentation != gGlobals->fColorPalette->GetPresentation() &&
  2070.         tPresentation != gGlobals->fToolPalette->GetPresentation()  )
  2071.     {
  2072.         frame->SetPresentation(ev, gGlobals->fMainPresentation);
  2073.         isMainPresentation = kODTrue;
  2074.     }
  2075.     
  2076.     if ( frame->IsRoot(ev) )
  2077.     {
  2078.         // If the frame being added is a root frame, we know that a window
  2079.         // is associated with this frame. Notify ourselves that we need to 
  2080.         // clean it up when the frame goes away.
  2081.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2082.         frameInfo->SetShouldDisposeWindow(kODTrue);
  2083.         
  2084.         // In addition, we need to verify that the frame is in "frame" view.
  2085.         // If the user dragged an icon from a document to Finder and then
  2086.         // opens the resultant document, the view would be "icon". However
  2087.         // displaying a icon is useless, so we need to change the view to
  2088.         // frame.
  2089.         if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  2090.             frame->SetViewType(ev, gGlobals->fFrameView);    
  2091.     }
  2092.     
  2093.     if (isMainPresentation)
  2094.     {
  2095.         // Ensure that embedded content is re-attached to saved frames correctly.
  2096.         COrdListIterator iter(fShapeList);
  2097.         if (fShapeList)
  2098.             for ( CShape* shape = (CShape*)iter.First();
  2099.                  iter.IsNotComplete();
  2100.                  shape = (CShape*)iter.Next() )
  2101.             {
  2102.                 shape->DisplayFrameConnected(ev, frame);
  2103.             }
  2104.     }
  2105.         
  2106.     // Only frame with gGlobals->fMainPresentation are droppable.
  2107.     if (frame->GetPresentation(ev)==gGlobals->fMainPresentation)
  2108.             frame->SetDroppable(ev, kODTrue);
  2109.         
  2110.     // Iterate over our display collection to match the frame with
  2111.     // an existing proxy with the correct frame ID. If we find it,
  2112.     // replace the ID with the actual frame. If we don't find it,
  2113.     // signal an error.
  2114.     ODBoolean found = kODFalse;
  2115.     COrdListIterator fiter(fDisplayFrameProxies);
  2116.     for ( CDisplayFrameProxy* proxy = (CDisplayFrameProxy*) fiter.First();
  2117.             fiter.IsNotComplete(); proxy = (CDisplayFrameProxy*) fiter.Next() )
  2118.     {
  2119.         if ( proxy->GetFrameID() == frame->GetID(ev) )
  2120.         {
  2121.             // Set the proxy as internalized, if it is not already.
  2122.             if (!proxy->IsFrameInMemory())
  2123.                 proxy->SetFrame(frame);
  2124.             
  2125.             found = kODTrue;
  2126.         }
  2127.     }
  2128.  
  2129.     // If we didn't find a proxy, then create one.
  2130.     if ( !found )
  2131.     {
  2132.         CDisplayFrameProxy* tProxy = new CDisplayFrameProxy();
  2133.         tProxy->InitializeDisplayFrameProxy(ev, this, kODNULLID, frame);
  2134.         fDisplayFrameProxies->AddLast(tProxy);
  2135.     
  2136.         // Since we maintain a persistent list of weak references to our
  2137.         // persistent display frames, having one added to the part dirties it.
  2138.         if (isMainPresentation)
  2139.             this->SetDirty(ev);
  2140.     }
  2141.     
  2142.     // We've deferred registering our internalized links until now, so that 
  2143.     // any updates that are precipitated can be added to the selection and redrawn.
  2144.     
  2145.     COrdListIterator sLinkIte(fSubscribeLinks);
  2146.     for (CSubscribeLink* slink = (CSubscribeLink *)sLinkIte.First(); sLinkIte.IsNotComplete(); slink = (CSubscribeLink *)sLinkIte.Next())
  2147.     {
  2148.         slink->Register(ev);
  2149.     }
  2150. }
  2151.  
  2152. //------------------------------------------------------------------------------
  2153. // Method:        CleanupDisplayFrame
  2154. // Origin:        DrawEditor
  2155. //
  2156. // Description:    This method is called when a frame has been closed or removed.
  2157. //                The method cleans up the references and state information stored
  2158. //                in the CFrameInfo class.
  2159. //------------------------------------------------------------------------------
  2160.  
  2161. void DrawEditor::CleanupDisplayFrame(    Environment*    ev,
  2162.                                         ODFrame*        frame,
  2163.                                         ODBoolean        frameRemoved )
  2164. {
  2165.     SOM_Trace("DrawEditor","CleanupDisplayFrame");
  2166.  
  2167.     ODError        error = noErr;
  2168.     CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2169.  
  2170.     TRY
  2171.         // If we are the root of a child window, we need to notify
  2172.         // our source frame that we are going away.
  2173.         if ( frameInfo->HasSourceFrame() )
  2174.         {
  2175.             ODFrame* sourceFrame = frameInfo->GetSourceFrame();
  2176.             CFrameInfo* sourceFrameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
  2177.             
  2178.             if ( frameRemoved )
  2179.             {
  2180.                 // Invalidate the source frame. We do this because the
  2181.                 // source frame may have a unique display when it has
  2182.                 // been opened into a part window. This forces the
  2183.                 // frame to redraw "not opened".
  2184.                 sourceFrame->Invalidate(ev, kODNULL, kODNULL);
  2185.             }
  2186.             
  2187.             // Release our reference to the source frame.
  2188.             frameInfo->ReleaseSourceFrame(ev);
  2189.             
  2190.             // Detach ourself from the source frame.
  2191.             sourceFrameInfo->DetachFrame(ev);
  2192.     
  2193.             // If the frame is the root, it is a part window going away
  2194.             // and we need to notify our source frame that it no longer
  2195.             // has a part window.
  2196.             if ( frame->IsRoot(ev) )
  2197.                 sourceFrameInfo->SetPartWindow(kODNULL);
  2198.         }
  2199.     CATCH_ALL
  2200.         error = ErrorCode();
  2201.     ENDTRY
  2202.     
  2203.     TRY
  2204.         // If the frame was removed from the document, we need to remove
  2205.         // any child window displaying that frame.
  2206.         if ( frameRemoved )
  2207.         {
  2208.             // If we have a child window, we need to close it.
  2209.             if ( frameInfo->HasPartWindow() )
  2210.             {
  2211.                 ODWindow* window = frameInfo->GetPartWindow();
  2212.                 frameInfo->SetPartWindow(kODNULL);
  2213.                 window->CloseAndRemove(ev);
  2214.             }
  2215.         }
  2216.     CATCH_ALL
  2217.         error = ErrorCode();
  2218.     ENDTRY
  2219.  
  2220.     TRY
  2221.         // If we have attached frames, we need to notify them that we
  2222.         // are going away.
  2223.     
  2224.         if ( frameInfo->HasAttachedFrame() )
  2225.         {
  2226.             CFrameInfo*    attachedFrameInfo;
  2227.             ODFrame*    attachedFrame = frameInfo->GetAttachedFrame();
  2228.             
  2229.             attachedFrameInfo = (CFrameInfo*) attachedFrame->GetPartInfo(ev);
  2230.             
  2231.             // Tell the attached frame that it's source is going away.
  2232.             attachedFrameInfo->ReleaseSourceFrame(ev);
  2233.             
  2234.             // Remove the attached frame from our state info.
  2235.             frameInfo->DetachFrame(ev);
  2236.         }
  2237.     CATCH_ALL
  2238.         error = ErrorCode();
  2239.     ENDTRY
  2240.     
  2241.     // If anything went wrong, signal an error.
  2242.     THROW_IF_ERROR(error);
  2243. }
  2244.  
  2245. //------------------------------------------------------------------------------
  2246. // Method:        DisplayFrameRemoved
  2247. // Origin:        ODPart
  2248. //
  2249. // Description:    This method is called in response to a frame being
  2250. //                removed from our part.
  2251. //
  2252. //                The part removes the frame from its internal display
  2253. //                frame list and reliquishes any foci that it still
  2254. //                owned. Lastly, if the frame has a source frame
  2255. //                (it was the root frame of a part window), we will
  2256. //                record the part window bounds so that any subsequent
  2257. //                part windows opened on the source frame will appear
  2258. //                in the same location.
  2259. //------------------------------------------------------------------------------
  2260.  
  2261. void DrawEditor::DisplayFrameRemoved( Environment*    ev,
  2262.                                       ODFrame*        frame )
  2263. {
  2264.     SOM_Trace("DrawEditor","DisplayFrameRemoved");
  2265.  
  2266.     ODBoolean isMainPresentation = frame->GetPresentation(ev)==gGlobals->fMainPresentation;
  2267.     
  2268.     TRY
  2269.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2270.         
  2271.         // Make sure the frame going away does not own any foci. Forgetting
  2272.         // to do this, will cause a "refcounting" error when the frame
  2273.         // is deleted by the draft.
  2274.         this->RelinquishAllFoci(ev, frame);
  2275.         
  2276.         // Notify any embedded content of frame being removed, if the frame
  2277.         // is in the main presentation
  2278.         if (frame->GetPresentation(ev)==gGlobals->fMainPresentation)
  2279.         {
  2280.             COrdListIterator iter(fShapeList);
  2281.             if (fShapeList)
  2282.                 for ( CShape* shape = (CShape*)iter.First();
  2283.                      iter.IsNotComplete();
  2284.                      shape = (CShape*)iter.Next() )
  2285.                 {
  2286.                     shape->DisplayFrameRemoved(ev, frame);
  2287.                 }
  2288.         }
  2289.         else
  2290.         {
  2291.             // Check and see if the frame being removed belonged
  2292.             // to one of our palettes. If so, then the window has
  2293.             // also closed. We should notify the palette.
  2294.             ODTypeToken presentation = frame->GetPresentation(ev);
  2295.             if (gGlobals->fColorPalette->GetPresentation() == presentation)
  2296.                 gGlobals->fColorPalette->ClosePalette(ev);
  2297.             else
  2298.             if (gGlobals->fToolPalette->GetPresentation() == presentation)
  2299.                 gGlobals->fToolPalette->ClosePalette(ev);
  2300.         }
  2301.         
  2302.         // Clean up the display frame.
  2303.         this->CleanupDisplayFrame(ev, frame, kFrameClosed);
  2304.         // Clean up any associated window.
  2305.         this->CleanupWindow(ev, frame);
  2306.         // Dispose of the frame's runtime state info.
  2307.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  2308.         ODDeleteObject(frameInfo);
  2309.         
  2310.         // Locate the proxy, and remove it
  2311.         COrdListIterator fiter(fDisplayFrameProxies);
  2312.         for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  2313.                 fiter.IsNotComplete();
  2314.                 frameProxy = (CDisplayFrameProxy*)fiter.Next())
  2315.         {
  2316.             // shouldn't get called to remove a frame that has
  2317.             // not yet been internalized
  2318.             if (frameProxy->IsFrameInMemory())
  2319.             {
  2320.                 if ( ODObjectsAreEqual(ev, frame,frameProxy->GetFrame(ev)) )
  2321.                 {
  2322.                     fiter.RemoveCurrent();
  2323.                     delete frameProxy;
  2324.                 }
  2325.             }
  2326.         }
  2327.         
  2328.         // Since we maintain a persistent list of weak references to our
  2329.         // persistent display frames, having one removed from the part dirties it.
  2330.         if (isMainPresentation)
  2331.             this->SetDirty(ev);
  2332.     
  2333.     CATCH_ALL
  2334.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  2335.         
  2336.         // Alert the caller.
  2337.         RERAISE;
  2338.     ENDTRY
  2339. }
  2340.  
  2341. //------------------------------------------------------------------------------
  2342. // Method:        DisplayFrameClosed
  2343. // Origin:        ODPart
  2344. //
  2345. // Description:    This method is called in response to a frame being
  2346. //                closed (not removed).
  2347. //
  2348. //                For a part as simple as this, we do not distinguish
  2349. //                between a frame being closed or removed. As such, we
  2350. //                just call DisplayFrameRemoved. 
  2351. //------------------------------------------------------------------------------
  2352.  
  2353. void DrawEditor::DisplayFrameClosed( Environment*    ev,
  2354.                                      ODFrame*        frame )
  2355. {
  2356.     SOM_Trace("DrawEditor","DisplayFrameClosed");
  2357.     
  2358.     TRY
  2359.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2360.     
  2361.         // Make sure the frame going away does not own any foci. Forgetting
  2362.         // to do this, will cause a "refcounting" error when the frame
  2363.         // is deleted by the draft.
  2364.         this->RelinquishAllFoci(ev, frame);
  2365.  
  2366.         // Clean up the display frame.
  2367.         this->CleanupDisplayFrame(ev, frame, kFrameClosed);
  2368.         // Clean up any associated window.
  2369.         this->CleanupWindow(ev, frame);
  2370.         // Dispose of the frame's runtime state info.
  2371.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  2372.         ODDeleteObject(frameInfo);
  2373.                     
  2374.         
  2375.         // Notify any embedded content of frame being removed, if the frame
  2376.         // is in the main presentation
  2377.         if (frame->GetPresentation(ev)==gGlobals->fMainPresentation)
  2378.         {
  2379.             COrdListIterator iter(fShapeList);
  2380.             if (fShapeList)
  2381.                 for ( CShape* shape = (CShape*)iter.First();
  2382.                      iter.IsNotComplete();
  2383.                      shape = (CShape*)iter.Next() )
  2384.                 {
  2385.                     shape->DisplayFrameClosed(ev, frame);
  2386.                 }
  2387.         }
  2388.         else
  2389.         {
  2390.             // Check and see if the frame being removed belonged
  2391.             // to one of our palettes. If so, then the window has
  2392.             // also closed. We should notify the palette.
  2393.             ODTypeToken presentation = frame->GetPresentation(ev);
  2394.             if (gGlobals->fColorPalette->GetPresentation() == presentation)
  2395.                 gGlobals->fColorPalette->ClosePalette(ev);
  2396.             else
  2397.             if (gGlobals->fToolPalette->GetPresentation() == presentation)
  2398.                 gGlobals->fToolPalette->ClosePalette(ev);
  2399.         }
  2400.  
  2401.         // Locate the proxy, and remove it
  2402.         COrdListIterator fiter(fDisplayFrameProxies);
  2403.         for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  2404.                 fiter.IsNotComplete();
  2405.                 frameProxy = (CDisplayFrameProxy*)fiter.Next())
  2406.         {
  2407.             // shouldn't get called to remove a frame that has
  2408.             // not yet been internalized
  2409.             if (frameProxy->IsFrameInMemory())
  2410.             {
  2411.                 if (frame==frameProxy->GetFrame(ev))
  2412.                 {
  2413.                     // Remove current makes the list consistent. This way
  2414.                     // we can modify the list while we are iterating over
  2415.                     // it.
  2416.                     fiter.RemoveCurrent();
  2417.                     delete frameProxy;
  2418.                 }
  2419.             }
  2420.         }
  2421.         
  2422.     CATCH_ALL
  2423.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  2424.         
  2425.         // Alert the caller.
  2426.         RERAISE;
  2427.     ENDTRY
  2428. }
  2429.  
  2430. //------------------------------------------------------------------------------
  2431. // Method:        AttachSourceFrame
  2432. // Origin:        ODPart
  2433. //
  2434. // Description:    If a part which we are contained in is opened into a
  2435. //                part window, it is required to iterate over its
  2436. //                embedded frames and add new display frames in the part
  2437. //                window. After each new embedded frame is created, this
  2438. //                method will be called.
  2439. //
  2440. //                Given all that, and given our lack of interesting
  2441. //                content, we just validate the frame. 
  2442. //------------------------------------------------------------------------------
  2443.  
  2444. void DrawEditor::AttachSourceFrame( Environment*    ev,
  2445.                                     ODFrame*        frame,
  2446.                                     ODFrame*        sourceFrame )
  2447. {
  2448.  
  2449.     SOM_Trace("DrawEditor","AttachSourceFrame");
  2450.  
  2451.     // Tell the new frame about its source.
  2452.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2453.     frameInfo->SetSourceFrame(ev, sourceFrame);
  2454.     
  2455.     // And tell the source about its new dependent.
  2456.     CFrameInfo* sourceFrameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
  2457.     sourceFrameInfo->AttachFrame(ev, frame);
  2458.     
  2459.     // In both cases, refcounting of the frame and sourceFrame is
  2460.     // handled by the CFrameInfo class.
  2461. }
  2462.  
  2463.  
  2464. //------------------------------------------------------------------------------
  2465. // Method:        RemoveEmbeddedFrame
  2466. // Origin:        ODPart
  2467. //
  2468. // Description:    This method is Called by an embedded part to indicate it no 
  2469. // longer needs the frame to display itself.
  2470. //------------------------------------------------------------------------------
  2471.  
  2472. void DrawEditor::RemoveEmbeddedFrame( Environment *ev, ODFrame* embeddedFrame )
  2473. {
  2474.     SOM_Trace("DrawEditor","RemoveEmbeddedFrame");
  2475.  
  2476.     CShape* tShape = this->ShapeForFrame(ev, embeddedFrame);
  2477.     THROW_IF_NULL(tShape);
  2478.     
  2479.     if (tShape->IsSelected())
  2480.     {
  2481.         fSelection->RemoveFromSelection(ev, tShape, kODTrue);    // Remove from Selection list
  2482.     }
  2483.     this->RemoveShape(ev, tShape);    // Remove from shape list
  2484.  
  2485.     // Remove the shape from content, and put the frame in "limbo"
  2486.     tShape->SetInLimbo(ev, kODTrue);
  2487.     tShape->Removed(ev, kCommit);
  2488. }
  2489.  
  2490.  
  2491. //------------------------------------------------------------------------------
  2492. // Method:        ViewTypeChanged
  2493. // Origin:        ODPart
  2494. //
  2495. // Description:    This method is called in response to one of our
  2496. //                display frame's viewType field being modified. We call
  2497. //                this method on ourselves when new display frames are
  2498. //                added, but it call also be called when the user
  2499. //                changes the view in the "part info" dialog.
  2500. //
  2501. //                The part first loads the appropriate view icons if
  2502. //                needed and then calculates a new "used" shape based on
  2503. //                the bounds of the new view type. If any problems occur
  2504. //                while changing the view, the part defaults back to 
  2505. //                frame view (the part's default view).
  2506. //------------------------------------------------------------------------------
  2507.  
  2508. void
  2509. DrawEditor::ViewTypeChanged( Environment*    ev,
  2510.                              ODFrame*        frame )
  2511. {
  2512.     SOM_Trace("DrawEditor","ViewTypeChanged");
  2513.  
  2514.     ODTypeToken    view = frame->GetViewType(ev);
  2515.     
  2516.     // Prepare to be displayed in a different view.
  2517.     if ( view == gGlobals->fThumbnailView )
  2518.         this->GenerateThumbnail(ev, frame);
  2519.         
  2520.     if ( view== gGlobals->fFrameView)
  2521.     {
  2522.         // Draw Content
  2523.         COrdListIterator iter(fShapeList);
  2524.         for (CShape* shape = (CShape*)iter.Last();
  2525.              iter.IsNotComplete(); 
  2526.              shape = (CShape*)iter.Previous())
  2527.         {
  2528.             shape->Show(ev, kODTrue);
  2529.         }
  2530.     }
  2531.     else
  2532.     {
  2533.         // Draw Content
  2534.         COrdListIterator iter(fShapeList);
  2535.         for (CShape* shape = (CShape*)iter.Last();
  2536.              iter.IsNotComplete(); 
  2537.              shape = (CShape*)iter.Previous())
  2538.         {
  2539.             // We must remove the shape from the selection if it is currently
  2540.             // selected since OpenDoc will send us an activate event which causes
  2541.             // the selection to be internalized.
  2542.             if (shape->IsSelected())
  2543.             {
  2544.                 fSelection->RemoveFromSelection(ev, shape, kODFalse);
  2545.             }
  2546.             shape->Show(ev, kODFalse);
  2547.         }
  2548.     }
  2549.             
  2550.     // Change this frame's used shape to match the new view setting.
  2551.     TempODShape newUsedShape = this->CalcNewUsedShape(ev, frame);    
  2552.  
  2553.     frame->Invalidate(ev, kODNULL, kODNULL);
  2554.     frame->ChangeUsedShape(ev, newUsedShape, kODNULL);
  2555.     frame->Invalidate(ev, kODNULL, kODNULL);
  2556.     
  2557. }
  2558.  
  2559. //------------------------------------------------------------------------------
  2560. // Method:        GenerateThumbnail
  2561. // Origin:        DrawEditor
  2562. //
  2563. // Description:    This method is called by the part to generate a 
  2564. //                thumbnail view from the current content.
  2565. //
  2566. //                The part has no content, so we merely load a picture.
  2567. //------------------------------------------------------------------------------
  2568.  
  2569. void DrawEditor::GenerateThumbnail( Environment*    ev,
  2570.                                     ODFrame*        frame )
  2571. {
  2572.     SOM_Trace("DrawEditor","GenerateThumbnail");
  2573.     
  2574.     // In cases where a part has been instantiated from scratch and has no
  2575.     // content (yet), it is appropriate to display a PICT or some graphic
  2576.     // in place of a "real" thumbnail.
  2577.     
  2578.     ::LoadThumbnail(ev, &gGlobals->fThumbnail);
  2579.  
  2580.     // If we were unable to load the PICT resource for whatever reason
  2581.     // we will default back to a "frame" view and throw the Resource
  2582.     // Manager error as an exception.
  2583.     if ( gGlobals->fThumbnail == kODNULL )
  2584.     {
  2585.         frame->ChangeViewType(ev, gGlobals->fFrameView);
  2586.         
  2587.         // There is a bug in ResError, when resources are not found,
  2588.         // which may cause noErr to be returned. If that is the case,
  2589.         // we throw resNotFound.
  2590.         THROW_IF_ERROR((ODError)ResError());
  2591.         THROW(resNotFound);
  2592.     }
  2593. }
  2594.  
  2595. //------------------------------------------------------------------------------
  2596. // Method:        UsedShapeChanged
  2597. // Origin:        ODPart
  2598. //
  2599. // Description:    Containing parts which have wrapped content to the used shape of 
  2600. // an embedded frame will need to adjust the layout of that content for the new used shape.
  2601. //------------------------------------------------------------------------------
  2602.  
  2603. void DrawEditor::UsedShapeChanged( Environment *ev, ODFrame* embeddedFrame)
  2604. {
  2605.     // Currently we do not support wrapping content to the used shape.
  2606.     SOM_Trace("DrawEditor","UsedShapeChanged");
  2607. }
  2608.  
  2609.  
  2610. //------------------------------------------------------------------------------
  2611. // Method:        FrameShapeChanged
  2612. // Origin:        ODPart
  2613. //
  2614. // Description:    This method is called in response to a frame's shape being
  2615. //                altered, either by the user or the part we are embedded in.
  2616. //
  2617. //                To keep all dependent frames in sync, we need to propogate the
  2618. //                new frame shape the frames dependent on the changed frame. This
  2619. //                is done by observing the display frames stored in the frame info
  2620. //                and calling RequestFrameShape for each.
  2621. //------------------------------------------------------------------------------
  2622.  
  2623. void DrawEditor::FrameShapeChanged( Environment*    ev,
  2624.                                     ODFrame*        frame )
  2625. {
  2626.     SOM_Trace("DrawEditor","FrameShapeChanged");
  2627.  
  2628.     // Adjust the "used" shape for the new frame shape.
  2629.     TempODShape usedShape = this->CalcNewUsedShape(ev, frame);
  2630.     frame->ChangeUsedShape(ev, usedShape, kODNULL);
  2631. }
  2632.  
  2633.  
  2634.  
  2635. //------------------------------------------------------------------------------
  2636. // Method:        AcquireFramesWindow
  2637. // Origin:        DrawEditor
  2638. //
  2639. // Description:    This method is called by the part when a frame, that has been
  2640. //                previously opened, is being opened again.
  2641. //
  2642. //                The method retrieves the existing window for the frame and
  2643. //                returns it.                
  2644. //------------------------------------------------------------------------------
  2645.  
  2646. ODWindow* DrawEditor::AcquireFramesWindow(    Environment*    ev,
  2647.                                                ODFrame*        frame )
  2648. {
  2649.     SOM_Trace("SamplePart","GetFramesWindow");
  2650.  
  2651.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2652.     ODWindow* window = frameInfo->GetPartWindow();
  2653.     ODAcquireObject(ev, window);
  2654.  
  2655.     return window;
  2656. }
  2657.     
  2658.  
  2659.  
  2660. //------------------------------------------------------------------------------
  2661. // Method:        Open
  2662. // Origin:        ODPart
  2663. //
  2664. // Description:    This method is called when OpenDoc, a containing part,
  2665. //                or the active editor would like to open a frame into
  2666. //                a seperate window. If a source frame is passed into
  2667. //                this method, the editor is being asked to open a part
  2668. //                window.
  2669. //
  2670. //                The part first checks to see if the display frame has
  2671. //                been opened into a window before (this will be true
  2672. //                if a source frame is passed in to the method and if
  2673. //                the source frame has a valid window ID). If there is
  2674. //                already a window displaying the frame, just bring that
  2675. //                window to the front. If not, we create a window from
  2676. //                scratch and display it.
  2677. //------------------------------------------------------------------------------
  2678.  
  2679. ODID DrawEditor::Open( Environment*    ev,
  2680.                        ODFrame*        frame )
  2681. {
  2682.     SOM_Trace("DrawEditor","Open");
  2683.  
  2684.     ODID windowID;
  2685.     ODWindow* window = kODNULL;
  2686.     WindowProperties* windowProperties = kODNULL;
  2687.     
  2688.     ODVolatile(window);
  2689.     ODVolatile(windowProperties);
  2690.  
  2691.     TRY
  2692.         // Because the frame parameter being passed to us can be one of
  2693.         // three things, we must determine what it is; either the root
  2694.         // frame of a existing document, the source frame for a part
  2695.         // window, or null if we are opening a new document.
  2696.     
  2697.         if ( frame == kODNULL )
  2698.         {
  2699.             // Calculate the bounding rectangle for a new window
  2700.             Rect windowRect = this->CalcPartWindowSize(ev, kODNULL);
  2701.             // Get the default setting for a document window.
  2702.             windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  2703.             // Create a Mac Window and register it with OpenDoc.
  2704.             window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  2705.         }
  2706.         else if ( frame->IsRoot(ev) )
  2707.         {
  2708.             // Get the previously saved settings for the document window.
  2709.             windowProperties = this->GetSavedWindowProperties(ev, frame);
  2710.             
  2711.             if ( windowProperties == kODNULL )
  2712.             {
  2713.                 // Calculate the bounding rectangle for a new window
  2714.                 Rect windowRect = this->CalcPartWindowSize(ev, frame);
  2715.                 // Get the default setting for a document window.
  2716.                 windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  2717.             }
  2718.  
  2719.             // Create a Mac Window and register it with OpenDoc.
  2720.             window = this->CreateWindow(ev, frame, kODFrameObject, windowProperties);
  2721.             
  2722.             // We release the source frame here because we didn't call
  2723.             // EndGetWindowProperties and becuase we are done with it.
  2724.             // ODReleaseObject(ev, windowProperties->sourceFrame);
  2725.         }
  2726.         else // frame is a source frame
  2727.         {
  2728.             window = this->AcquireFramesWindow(ev, frame);
  2729.     
  2730.             if ( window == kODNULL )
  2731.             {
  2732.                 // Calculate the bounding rectangle for a new window
  2733.                 Rect windowRect = this->CalcPartWindowSize(ev, frame);
  2734.                 // Get the default setting for a document window.
  2735.                 windowProperties = this->GetDefaultWindowProperties(ev, frame, &windowRect);
  2736.                 // Create a Mac Window and register it with OpenDoc.
  2737.                 window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  2738.                 
  2739.                 // Tell the source frame that it is opened in a part window.
  2740.                 CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2741.                 frameInfo->SetPartWindow(window);
  2742.             }
  2743.         }
  2744.     
  2745.         // Create the window's root facet.
  2746.         window->Open(ev);
  2747.         // Make the window visible.
  2748.         window->Show(ev);
  2749.         // Activate and select the window.
  2750.         window->Select(ev);
  2751.     
  2752.         // Cleanup allocate memory.
  2753.         ODDeleteObject(windowProperties);
  2754.         
  2755.         // Get window id to return.
  2756.         windowID = (window ? window->GetID(ev) : kODNULLID);
  2757.         ODReleaseObject(ev, window);
  2758.     
  2759.     CATCH_ALL
  2760.         // If we threw early, the source frame's refcount may be too high.
  2761.         if ( windowProperties )
  2762.             ODReleaseObject(ev, windowProperties->sourceFrame);
  2763.         // Cleanup the created items.
  2764.         ODDeleteObject(windowProperties);
  2765.         ODSafeReleaseObject(window);
  2766.         windowID = kODNULLID;
  2767.         // Alert the caller.
  2768.         RERAISE;
  2769.     ENDTRY
  2770.  
  2771.     return windowID;
  2772. }
  2773.  
  2774.     
  2775. //------------------------------------------------------------------------------
  2776. // Method:        CreateWindow
  2777. // Origin:        DrawEditor
  2778. //
  2779. // Description:    This method is called by the part when a window needs to be
  2780. //                created for a frame being opened.
  2781. //
  2782. //                The part uses the information passed in windowProperties to 
  2783. //                create the appropriate window. The generated window is
  2784. //                registered with OpenDoc as a new window (RegisterWindow) or as a
  2785. //                window from an existing document (RegisterWindowForFrame).
  2786. //------------------------------------------------------------------------------
  2787.  
  2788. ODWindow* DrawEditor::CreateWindow( Environment*         ev,
  2789.                                     ODFrame*            frame,
  2790.                                     ODType                frameType,
  2791.                                     WindowProperties*    windowProperties)
  2792. {
  2793.     SOM_Trace("DrawEditor","CreateWindow");
  2794.  
  2795.     ODPlatformWindow    platformWindow    = kODNULL;
  2796.     ODWindow*            window            = kODNULL;
  2797.     
  2798.     // Using the name and the calculated rectangle, create a new window.
  2799.     // Note that we are allocating the window record in temp mem using
  2800.     // the OpenDoc memory mgr. This helps reduce app heap usage.
  2801.     // In addition, OpenDoc requires that all new windows be initially hidden
  2802.     // so that it can correctly layer windows/palettes.
  2803.     platformWindow = ::NewCWindow((Ptr)::ODNewPtr(sizeof(WindowRecord)),
  2804.                                 &(windowProperties->boundsRect),
  2805.                                 windowProperties->title,
  2806.                                 kODFalse, /* visible */
  2807.                                 windowProperties->procID,
  2808.                                 (WindowPtr)-1L,
  2809.                                 windowProperties->hasCloseBox,
  2810.                                 windowProperties->refCon);
  2811.  
  2812.     if ( platformWindow )
  2813.     {
  2814.         TRY
  2815.             ODWindowState* windowState = ODGetSession(ev,fSelf)->GetWindowState(ev);
  2816.             
  2817.             // Shoud the window be saved in the document? Yes if the root frame is
  2818.             // persistent.
  2819.             ODBoolean saveWindow = (ODISOStrCompare(frameType,kODFrameObject) == 0);
  2820.             
  2821.             // Tell the window object that we will be disposing the window record
  2822.             // when the root frame is closed/removed.
  2823.             ODBoolean shouldDispose = kODFalse;
  2824.                                 
  2825.             // Determine whether we are creating a new window (frame is null),
  2826.             // or opening a previous saved window (frame is valid).
  2827.             
  2828.             if ( frame == kODNULL )
  2829.             {                                
  2830.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  2831.                 window = windowState->
  2832.                             RegisterWindow(ev, 
  2833.                                 platformWindow,                    // Macintosh WindowPtr
  2834.                                 frameType,                        // Frame type (Persistent/Non-persistent)
  2835.                                 windowProperties->isRootWindow,    // Is this a document window?
  2836.                                 windowProperties->isResizable,    // Is this window resizeable?
  2837.                                 windowProperties->isFloating,    // Is this window floating?
  2838.                                 saveWindow,                        // Should this window be persistent?
  2839.                                 shouldDispose,                    // (see comment above)
  2840.                                 fSelf,                            // Part reference to us
  2841.                                 gGlobals->fFrameView,            // What view should the window have?
  2842.                                 gGlobals->fMainPresentation,    // What presentation should the window have?
  2843.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  2844.             }
  2845.             else
  2846.             {
  2847.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  2848.                 window = windowState->
  2849.                             RegisterWindowForFrame(ev, 
  2850.                                 platformWindow,                    // Macintosh WindowPtr
  2851.                                 frame,                             // Frame type (Persistent/Non-persistent)
  2852.                                 windowProperties->isRootWindow,    // Is this a document window?
  2853.                                 windowProperties->isResizable,    // Is this window resizeable?
  2854.                                 windowProperties->isFloating,    // Is this window floating?
  2855.                                 saveWindow,                        // Should this window be persistent?
  2856.                                 shouldDispose,                    // (see comment above)
  2857.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  2858.             }
  2859.             
  2860.         CATCH_ALL
  2861.             // Cleanup Macintosh Window.
  2862.             CloseWindow(platformWindow);
  2863.             ODDisposePtr(platformWindow);
  2864.             // Get the right error message for the problem.
  2865.             ODSShort errMsgNum = (!frame && windowProperties->sourceFrame)
  2866.                                     ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
  2867.             // Alert the user of the problem.
  2868.             this->DoDialogBox(ev, frame, kErrorBoxID, errMsgNum);
  2869.             // Change the exception value, so the DocShell doesn't display an
  2870.             // error dialog.
  2871.             SetErrorCode(kODErrAlreadyNotified);
  2872.             // Alert the caller.
  2873.             RERAISE;
  2874.         ENDTRY
  2875.     }
  2876.  
  2877.     return window;
  2878. }
  2879.  
  2880. //------------------------------------------------------------------------------
  2881. // Method:        CleanupWindow
  2882. // Origin:        DrawEditor
  2883. //
  2884. // Description:    This method is called by the part when a window needs to be
  2885. //                cleaned up for a frame being closed/removed.
  2886. //
  2887. //                The part deallocates the window buffer allocated in the
  2888. //                CreateWindow() method.
  2889. //------------------------------------------------------------------------------
  2890.  
  2891. void DrawEditor::CleanupWindow( Environment*     ev,
  2892.                                 ODFrame*        frame )
  2893. {
  2894.     SOM_Trace("DrawEditor","CleanupWindow");
  2895.     
  2896.        TRY
  2897.         CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2898.         if ( frameInfo->ShouldDisposeWindow() )
  2899.         {
  2900.             TempODWindow window = frame->AcquireWindow(ev);
  2901.             THROW_IF_NULL(window);
  2902.             
  2903.             ODPlatformWindow windowPtr = window->GetPlatformWindow(ev);
  2904.             CloseWindow(windowPtr);
  2905.             ODDisposePtr(windowPtr);
  2906.         }
  2907.     CATCH_ALL
  2908.         this->DoDialogBox(ev, frame, kErrorBoxID, kErrWindowGone);
  2909.         // consume excpetion because it's not fatal.
  2910.     ENDTRY
  2911. }
  2912.  
  2913.  
  2914. //------------------------------------------------------------------------------
  2915. // Method:        GetDefaultWindowProperties
  2916. // Origin:        DrawEditor
  2917. //
  2918. // Description:    This method is called by the part when a new window is being
  2919. //                created. The method examines the frame which is being opened
  2920. //                a generates the default window parameters to pass to the
  2921. //                Mac Toolbox.
  2922. //------------------------------------------------------------------------------
  2923.  
  2924. WindowProperties*
  2925. DrawEditor::GetDefaultWindowProperties( Environment*     ev,
  2926.                                         ODFrame*        sourceFrame,
  2927.                                         Rect*            windowRect )
  2928. {
  2929.     SOM_Trace("DrawEditor","GetDefaultWindowProperties");
  2930.     
  2931.     WindowProperties*    windowProperties = new WindowProperties;
  2932.     ODIText*            windowName;
  2933.  
  2934.     // Calculate the offset for the window based on the sourceFrame.    
  2935.     if ( sourceFrame )
  2936.         this->CalcPartWindowPosition(ev, sourceFrame, windowRect);
  2937.     else
  2938.         OffsetRect(windowRect, kALittleNudge,
  2939.                     GetMBarHeight() + kMacWindowTitleBarHeight);    
  2940.  
  2941.     windowProperties->boundsRect = *windowRect;
  2942.  
  2943.     // Get the part name to use for the new window. If we can't
  2944.     // get a valid name for the part, we generate one using the user
  2945.     // visible category name of the part's category.
  2946.     windowName = ODGetITextProp(ev, fSelf->GetStorageUnit(ev), kODPropName, 
  2947.                                     kODMacIText, kODNULL);
  2948.                                     
  2949.     if ( (windowName == kODNULL) || (GetITextStringLength(windowName) == 0) )
  2950.     {
  2951.         ODNameSpaceManager* nsMgr = ODGetSession(ev,fSelf)->GetNameSpaceManager(ev);
  2952.                     
  2953.         // Get the category string from the category name space.
  2954.         if ( !GetUserCatFromCat(nsMgr, kODCategoryDrawing, &windowName) )
  2955. #if ODDebug
  2956.             // This should never happen. Check NMAP for errors.
  2957.             DebugStr("\pCategory NMAP bad, or Preferences corrupted.");
  2958. #else
  2959.             THROW(kODErrInvalidNSType);
  2960. #endif
  2961.     }
  2962.  
  2963.     // Convert the ODIText into a Pascal string.
  2964.     GetITextString(windowName, windowProperties->title);
  2965.     // Dispose of the name object.
  2966.     DisposeIText(windowName);
  2967.     
  2968.     // Fill in the other fields of the Window Properties struct.
  2969.     
  2970.     windowProperties->procID = zoomDocProc;
  2971.     windowProperties->hasCloseBox = kODTrue;
  2972.     windowProperties->refCon = (long) kODNULL;
  2973.     windowProperties->wasVisible = kODFalse;
  2974.     windowProperties->isResizable = kODTrue;
  2975.     windowProperties->isFloating = kODFalse;
  2976.     windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
  2977.     windowProperties->shouldShowLinks = kODFalse;
  2978.     windowProperties->sourceFrame = sourceFrame;
  2979.     
  2980.     return windowProperties;
  2981. }
  2982.  
  2983. //------------------------------------------------------------------------------
  2984. // Method:        GetSavedWindowProperties
  2985. // Origin:        DrawEditor
  2986. //
  2987. // Description:    This method is called by the part to read in saved information
  2988. //                for a window from an existing document.
  2989. //------------------------------------------------------------------------------
  2990.  
  2991. WindowProperties*
  2992. DrawEditor::GetSavedWindowProperties( Environment*     ev,
  2993.                                       ODFrame*        frame )
  2994. {
  2995.     SOM_Trace("DrawEditor","GetSavedWindowProperties");
  2996.  
  2997.     WindowProperties* windowProperties = new WindowProperties;
  2998.     
  2999.     // If we fail to load the window properties from storage, delete
  3000.     // the structure so the calling code will behave appropriately.    
  3001.     if ( !BeginGetWindowProperties(ev, frame, windowProperties) )
  3002.     {
  3003.         ODDeleteObject(windowProperties);
  3004.         EndGetWindowProperties(ev, windowProperties);
  3005.         return kODNULL;
  3006.     }
  3007.     else
  3008.         EndGetWindowProperties(ev, windowProperties);
  3009.     
  3010.     // Note: We don't call EndGetWindowProperties because it releases the
  3011.     // source frame, which we will need after this method returns.
  3012.     
  3013.     // Verify the window is still visible on a monitor.
  3014.     
  3015.     RgnHandle windowRgn = ODNewRgn();
  3016.     ODBoolean repositionWindow = kODFalse;
  3017.     
  3018.     // We are only concerned with the window's title bar being
  3019.     // visible, so calcuate the titlebar rect from the current
  3020.     // window bounds.
  3021.     Rect adjustedBounds = windowProperties->boundsRect;
  3022.     adjustedBounds.bottom = adjustedBounds.top;
  3023.     adjustedBounds.top -= kMacWindowTitleBarHeight;
  3024.     
  3025.     // Intersect the monitor's region
  3026.     RectRgn(windowRgn, &adjustedBounds);
  3027.     SectRgn(windowRgn, GetGrayRgn(), windowRgn);
  3028.     
  3029.     if ( !EmptyRgn(windowRgn) )
  3030.     {
  3031.         // If the visible portion of the window is too small, we need
  3032.         // to reposition it.
  3033.         Rect intersectedBounds = (**windowRgn).rgnBBox;
  3034.         if ( (intersectedBounds.right-intersectedBounds.left < kMinHorzVisPortion) ||
  3035.                 (intersectedBounds.bottom-intersectedBounds.top < kMinVertVisPortion) )
  3036.             repositionWindow = kODTrue;
  3037.     }
  3038.     else
  3039.     {
  3040.         // If the window is completely offscreen, we need to reposition it.
  3041.         repositionWindow = kODTrue;
  3042.     }
  3043.     ODDisposeHandle((ODHandle)windowRgn);
  3044.     
  3045.     // If not, we need to move it so the user can see it.
  3046.     if ( repositionWindow )
  3047.     {
  3048.         Rect windowRect = (windowProperties->boundsRect);
  3049.         // Move the window to {0,0} coordinates.
  3050.         OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  3051.         // Now move the window to the default window position.
  3052.         OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
  3053.         // Save the new window position in our windowProperties.
  3054.         windowProperties->boundsRect = windowRect;
  3055.     }
  3056.     
  3057.     return windowProperties;
  3058. }
  3059.  
  3060. //------------------------------------------------------------------------------
  3061. // Method:        CalcPartWindowSize
  3062. // Origin:        DrawEditor
  3063. //
  3064. // Description:    This method is called by the part to determine what
  3065. //                size a new window should be.
  3066. //------------------------------------------------------------------------------
  3067.  
  3068. Rect DrawEditor::CalcPartWindowSize( Environment*    ev,
  3069.                                       ODFrame*        sourceFrame )
  3070. {
  3071.     SOM_Trace("DrawEditor","CalcPartWindowSize");
  3072.  
  3073.     const ODSShort kOnePageWidth = 600;
  3074.     
  3075.     Rect    windowRect;
  3076.     ODRect    frameRect;
  3077.     
  3078.     // If a source frame is given, the part is being asked to open one of
  3079.     // its display frames into a part window. Otherwise, we are being opened
  3080.     // as the root frame of the current document and should size the window
  3081.     // accordingly.
  3082.  
  3083.     // Set up the child window's size to be that of the display frame being opened.
  3084.     if ( sourceFrame )
  3085.     {
  3086.         // Retrieve the fixed point bounding box for the frame.
  3087.         ODShape* frameShape = sourceFrame->AcquireFrameShape(ev, kODNULL);
  3088.         frameShape->GetBoundingBox(ev, &frameRect);
  3089.         
  3090.         // Convert that into a Quickdraw rectangle.
  3091.         FixedToIntRect(frameRect, windowRect);
  3092.             
  3093.         ODReleaseObject(ev,frameShape);
  3094.     }
  3095.     // Otherwise, just open a large window.
  3096.     else
  3097.     {
  3098.         // (3 * kODLargeIconSize) prevents the window from covering the volume
  3099.         // icons on the desktop which is a violation of Macintosh HI Guidelines.
  3100.         
  3101.         SetRect(&windowRect, 0, 0,
  3102.                   ODQDGlobals.screenBits.bounds.right - (3 * kODLargeIconSize),
  3103.                   ODQDGlobals.screenBits.bounds.bottom
  3104.                       - GetMBarHeight() - kMacWindowTitleBarHeight - kALittleNudge);        
  3105.         
  3106.         if ( windowRect.right - windowRect.left > kOnePageWidth )
  3107.             windowRect.right = windowRect.left + kOnePageWidth;
  3108.     }
  3109.     
  3110.     return windowRect;
  3111. }
  3112.  
  3113. //------------------------------------------------------------------------------
  3114. // Method:        CalcPartWindowPosition
  3115. // Origin:        DrawEditor
  3116. //
  3117. // Description:    This method is called by the part to determine where
  3118. //                to align the new window (top left corner of the screen
  3119. //                or tiled to a frame).
  3120. //------------------------------------------------------------------------------
  3121.  
  3122. Rect DrawEditor::CalcPartWindowPosition( Environment*    ev,
  3123.                                           ODFrame*        frame,
  3124.                                           Rect*            partWindowBounds )
  3125. {
  3126.     SOM_Trace("DrawEditor","CalcPartWindowPosition");
  3127.  
  3128.     ODFacet*        activeFacet;
  3129.     ODShape*        frameShape;
  3130.     ODRect            bbox;
  3131.     Rect            bounds;
  3132.     
  3133.     // We need to know which facet of the frame we are opening to position
  3134.     // the child window.
  3135.     activeFacet = this->GetActiveFacetForFrame(ev, frame);
  3136.     
  3137.     // This should never occur, but if it did, it would be fatal.
  3138.     // So we will just pass back the same rectangle.
  3139.     if ( activeFacet == kODNULL )
  3140.         return *partWindowBounds;
  3141.     
  3142.     // For the purposes of tiling, we need the to know the area of the
  3143.     // document the frame occupies. We do this by getting the bouding
  3144.     // box and offsetting it by the aggregate external window transform
  3145.     // of the facet.
  3146.     
  3147.     frameShape = activeFacet->GetFrame(ev)->AcquireFrameShape(ev, kODNULL);
  3148.     TempODTransform windowFrameTransform = activeFacet->AcquireWindowFrameTransform(ev, kODNULL);
  3149.     TempODShape boundsShape = ODCopyAndRelease(ev, frameShape);
  3150.  
  3151.     // Translate the bounds rect into window coordinates.
  3152.     boundsShape->Transform(ev, windowFrameTransform);
  3153.     
  3154.     // Get and convert the bounding box into a QuickDraw rectangle.
  3155.     boundsShape->GetBoundingBox(ev, &bbox);
  3156.     FixedToIntRect(bbox, bounds);
  3157.         
  3158.     // We then call our method to tile the child window.
  3159.     *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
  3160.     
  3161.     // Set the port and origin so we can convert the rect to
  3162.     // global Window Mgr coordinates.
  3163.     SetPort(activeFacet->GetCanvas(ev)->GetQDPort(ev));
  3164.     SetOrigin(0,-kMacWindowTitleBarHeight);
  3165.     
  3166.     // Convert the local coordinates to global Window Mgr coordinates.
  3167.     LocalToGlobal((Point*)(&(partWindowBounds->top)));
  3168.     LocalToGlobal((Point*)(&(partWindowBounds->bottom)));
  3169.     
  3170.     return *partWindowBounds;
  3171. }
  3172.  
  3173. //------------------------------------------------------------------------------
  3174. // Method:        GetActiveFacetForFrame
  3175. // Origin:        DrawEditor
  3176. //
  3177. // Description:    This method is called by the part when it needs to 
  3178. //                know what the active facet is for the part, if any.
  3179. //
  3180. //                The part uses this method specifically to find the
  3181. //                facet of a source frame when opening a part window.
  3182. //------------------------------------------------------------------------------
  3183.  
  3184. ODFacet* DrawEditor::GetActiveFacetForFrame( Environment*    ev,
  3185.                                              ODFrame*        frame )
  3186. {
  3187.     SOM_Trace("DrawEditor","GetActiveFacetForFrame");
  3188.  
  3189.     ODFacet*        facet = kODNULL;
  3190.     CFrameInfo*        frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  3191.     
  3192.     // If the frame is active, and it should be, get the active facet
  3193.     // from the frame state info.
  3194.     if ( frameInfo->IsFrameActive() )
  3195.     {
  3196.         facet = frameInfo->GetActiveFacet();
  3197.     }
  3198.     else
  3199.     // Otherwise, iterate over the display frames looking for one
  3200.     // that has an active facet... there should be at least one.
  3201.     {
  3202.         ODFacet*    selectedFacet;
  3203.         ODBoolean    foundSelectedFacet = kODFalse;
  3204.         
  3205.         ODFrameFacetIterator* fiter = frame->CreateFacetIterator(ev);
  3206.         for ( selectedFacet = fiter->First(ev);
  3207.                                fiter->IsNotComplete(ev);
  3208.               selectedFacet = fiter->Next(ev) )
  3209.         {
  3210.             if ( selectedFacet->IsSelected(ev) )
  3211.             {
  3212.                 foundSelectedFacet = kODTrue;
  3213.                 break;
  3214.             }
  3215.         }
  3216.         
  3217.         facet = selectedFacet;
  3218.             
  3219.         ODDeleteObject(fiter);
  3220.     }
  3221.     
  3222.     return facet;
  3223. }
  3224.  
  3225. //------------------------------------------------------------------------------
  3226. // Method:        CalcNewUsedShape
  3227. // Origin:        DrawEditor
  3228. //
  3229. // Description:    This method is called in response to one of display frame's view
  3230. //                being changed. The method calculates the appropriate usedShape
  3231. //                for the new view type.
  3232. //------------------------------------------------------------------------------
  3233.  
  3234. ODShape* DrawEditor::CalcNewUsedShape( Environment*    ev,
  3235.                                          ODFrame*        frame )
  3236. {
  3237.     SOM_Trace("DrawEditor","CalcNewUsedShape");
  3238.  
  3239.     ODShape* usedShape = kODNULL;        ODVolatile(usedShape);
  3240.     RgnHandle usedRgn;                    ODVolatile(usedRgn);
  3241.     
  3242.     // If the view is "frame", we intentionally return a nil shape;
  3243.     // doing so, will reset the used shape to equal the frame shape.
  3244.  
  3245.     ODTypeToken view = frame->GetViewType(ev);
  3246.  
  3247.     if ( view == gGlobals->fLargeIconView ||
  3248.             view == gGlobals->fSmallIconView ||
  3249.             view == gGlobals->fThumbnailView )
  3250.     {
  3251.         TRY
  3252.             Rect bounds;
  3253.             usedRgn = ODNewRgn();
  3254.  
  3255.             if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  3256.             {
  3257.                 CUsingLibraryResources res;
  3258.  
  3259.                 // Set the bounds rect for the icon size.
  3260.                 SetRect(&bounds, 0, 0,
  3261.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
  3262.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
  3263.  
  3264.                 // Convert the icon mask into a Region.
  3265.                 THROW_IF_ERROR( IconIDToRgn(usedRgn, &bounds, atAbsoluteCenter, kBaseResourceID) );
  3266.             }
  3267.             else if ( view == gGlobals->fThumbnailView )
  3268.             {    
  3269.                 bounds = (**(PicHandle)gGlobals->fThumbnail).picFrame;
  3270.                 RectRgn(usedRgn,&bounds);
  3271.             }
  3272.         
  3273.             usedShape = frame->CreateShape(ev);
  3274.             usedShape->SetQDRegion(ev, usedRgn);
  3275.                             
  3276.         CATCH_ALL
  3277.             ODSafeReleaseObject(usedShape);
  3278.             ODDisposeHandle((ODHandle)usedRgn);
  3279.             usedShape = kODNULL;
  3280.         ENDTRY
  3281.     }
  3282.         
  3283.     return usedShape;
  3284. }
  3285.  
  3286. //------------------------------------------------------------------------------
  3287. // Origin:        DrawEditor
  3288. //
  3289. // Description:    This method is called in response to one of our
  3290. //------------------------------------------------------------------------------
  3291.  
  3292. void
  3293. DrawEditor::UpdateFrame( Environment*    ev,
  3294.                          ODFrame*        frame,
  3295.                          ODTypeToken    view,
  3296.                          ODShape*        usedShape )
  3297. {
  3298.     SOM_Trace("DrawEditor","UpdateFrame");
  3299.  
  3300.     // Update the frame to have the new view and UsedShape.
  3301.     frame->Invalidate(ev, kODNULL, kODNULL);
  3302.     frame->SetViewType(ev, view);
  3303.     frame->ChangeUsedShape(ev, usedShape, kODNULL);
  3304.     frame->Invalidate(ev, kODNULL, kODNULL);
  3305. }
  3306.  
  3307. //------------------------------------------------------------------------------
  3308. // Method:        FacetAdded
  3309. // Origin:        ODPart
  3310. //
  3311. // Description:    This method is called when any part adds a facet to
  3312. //                one of our display frames.
  3313. //
  3314. //                The part calls ViewTypeChanged to load the appropriate
  3315. //                resource for display in this facet and then activates
  3316. //                the frame if we are the root part of an active window.
  3317. //------------------------------------------------------------------------------
  3318.  
  3319. void DrawEditor::FacetAdded( Environment*    ev,
  3320.                              ODFacet*        facet )
  3321. {
  3322.     SOM_Trace("DrawEditor","FacetAdded");
  3323.  
  3324.     ODFrame* frame = facet->GetFrame(ev);
  3325.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  3326.  
  3327.     ODBoolean isMainPresentation = facet->GetFrame(ev)->
  3328.             GetPresentation(ev)==gGlobals->fMainPresentation;
  3329.     
  3330.     // Notify our embedded content of the new facet, Only  if it is not a palette
  3331.     if (isMainPresentation)
  3332.     {
  3333.         COrdListIterator iter(fShapeList);
  3334.         if (fShapeList)
  3335.             for ( CShape* shape = (CShape*)iter.First();
  3336.                  iter.IsNotComplete();
  3337.                  shape = (CShape*)iter.Next() )
  3338.             {
  3339.                 shape->FacetAdded(ev, facet);
  3340.             }
  3341.     
  3342.         // We call this to prepare our part for being displayed in one of
  3343.         // the four standard views: Large Icon, Small Icon, Frame, and
  3344.         // Thumbnail.
  3345.         this->ViewTypeChanged(ev, frame);
  3346.             
  3347.         // If this is the root frame/facet of a given window and it is NOT in a palette
  3348.         // we should activate ourselves. 
  3349.         if (frame->IsRoot(ev))
  3350.         {
  3351.             if ( this->ActivateFrame(ev, frame) )
  3352.                 frameInfo->SetActiveFacet(facet);
  3353.         }
  3354.     
  3355.         // If a frame had all of its facets removed, the frame would have
  3356.         // hidden any of its part windows. If the frame becomes visible again,
  3357.         // by having a facet added to it, we will "show" the part window for
  3358.         // the frame. Except, in the case where are a frame could be scrolled out of view,
  3359.         // and purged. When scrolling is implemented this will need to change.
  3360.         
  3361.         if ( (CountFramesFacets(ev, frame) == 1) )
  3362.         {
  3363.             if ( frameInfo->HasPartWindow() )
  3364.                 frameInfo->GetPartWindow()->Show(ev);
  3365.         }
  3366.         
  3367.         // Only clip the facet if it is not a palette
  3368.         this->ClipEmbeddedFacets(ev, facet);
  3369.         
  3370.     }
  3371.     
  3372. }
  3373.  
  3374. //------------------------------------------------------------------------------
  3375. // Method:        FacetRemoved
  3376. // Origin:        ODPart
  3377. //
  3378. // Description:    This method is called when any part removes a facet
  3379. //                from one of our display frames.
  3380. //
  3381. //                The part just removes the "active" note from the
  3382. //                appropriate display frame if necessary since this
  3383. //                facet will not be available, nor active, again.
  3384. //------------------------------------------------------------------------------
  3385.  
  3386. void DrawEditor::FacetRemoved( Environment*    ev,
  3387.                                ODFacet*        facet )
  3388. {
  3389.     SOM_Trace("DrawEditor","FacetRemoved");
  3390.  
  3391.     ODFrame*    frame = facet->GetFrame(ev);
  3392.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  3393.  
  3394.     ODBoolean isMainPresentation = frame->GetPresentation(ev)==gGlobals->fMainPresentation;
  3395.     
  3396.     // If the facet was the active facet, it can no longer be.
  3397.     if ( frameInfo->GetActiveFacet() == facet )
  3398.         frameInfo->SetActiveFacet(kODNULL);
  3399.  
  3400.     // If a frame has all of its facets removed, the frame becomes
  3401.     // "hidden". If the frame a part window, the part window should also
  3402.     // be hidden. This may need to change when scrolling is implemented.
  3403.     // The case where a frame is scrolled out of view and purged temprorarily, its
  3404.     // part window may remain visible.
  3405.     
  3406.     
  3407.     if (isMainPresentation)
  3408.     {
  3409.         if ( (CountFramesFacets(ev, frame) == 0) )
  3410.         {
  3411.             if ( frameInfo->HasPartWindow() )
  3412.                 frameInfo->GetPartWindow()->Hide(ev);
  3413.         }
  3414.         
  3415.         // Remove any embedded facets of the given facet
  3416.         COrdListIterator iter(fShapeList);
  3417.         if (fShapeList)
  3418.             for ( CShape* shape = (CShape*)iter.First();
  3419.                  iter.IsNotComplete();
  3420.                  shape = (CShape*)iter.Next() )
  3421.             {
  3422.                 shape->FacetRemoved(ev, facet);
  3423.             }
  3424.     }
  3425.  
  3426. }
  3427.  
  3428. //------------------------------------------------------------------------------
  3429. // Method:        RequestFrameShape
  3430. // Origin:        ODPart
  3431. //
  3432. // Description:    An embedded part has asked to change the shape of its frame.
  3433. //
  3434. //------------------------------------------------------------------------------
  3435.  
  3436. ODShape* DrawEditor::RequestFrameShape(Environment *ev, ODFrame* embeddedFrame,
  3437.                                         ODShape* frameShape)
  3438. {
  3439.     // Grant any shape, for the time being
  3440.     
  3441.     ODShape* contentShape = kODNULL;
  3442.     
  3443.     TRY
  3444.         // First make a copy of the incoming shape
  3445.         contentShape = frameShape->Copy(ev);
  3446.         
  3447.         // Find the shape representing the given frame and resize it
  3448.         CShape* tShape = this->ShapeForFrame(ev, embeddedFrame);
  3449.         THROW_IF_NULL(tShape);
  3450.     
  3451.         // Transform the shape before setting the content bounds
  3452.         Point offset;
  3453.         Rect tRect;
  3454.         
  3455.         tShape->GetBoundingBox(&tRect);
  3456.         offset.h = tRect.left;
  3457.         offset.v = tRect.top;
  3458.         
  3459.         TempODTransform tTransform = embeddedFrame->CreateTransform(ev);
  3460.         tTransform->SetQDOffset(ev, &offset);
  3461.         contentShape->Transform(ev, tTransform);
  3462.         
  3463.         // Change the embedded content's bounding rectangle, without
  3464.         // causing the actual ODFrame to be resized.
  3465.         if (tShape->GetShapeType() == kEmbeddingShape)
  3466.         {
  3467.             ((CEmbeddingShape*)tShape)->SetShapeRectangle(ev, contentShape);
  3468.         }
  3469.         #ifdef ODDebug
  3470.         else
  3471.             DebugStr("\pThis shape really should be an embedding shape!");
  3472.         #endif
  3473.         
  3474.         // Redraw the shape with its new bounds
  3475.         this->InvalidateShape(ev, tShape);
  3476.     
  3477.     CATCH_ALL
  3478.         #ifdef ODDebug
  3479.         DebugStr("\pThis frame is NOT embedded in this part!");
  3480.         #endif
  3481.         
  3482.         return kODNULL;
  3483.     ENDTRY
  3484.     
  3485.     // The leaf part will release this shape
  3486.     ODAcquireObject(ev, frameShape);
  3487.     return frameShape;
  3488. }
  3489.  
  3490.  
  3491. //------------------------------------------------------------------------------
  3492. // Method:        RequestEmbeddedFrame
  3493. // Origin:        ODPart
  3494. //
  3495. // Description:    An embedded part has asked for an additional frame.
  3496. //
  3497. //------------------------------------------------------------------------------
  3498. ODFrame* DrawEditor::RequestEmbeddedFrame(Environment* ev,
  3499.                                             ODFrame* containingFrame, 
  3500.                                             ODFrame* baseFrame,
  3501.                                             ODShape* frameShape,
  3502.                                             ODPart* embedPart,
  3503.                                             ODTypeToken viewType,
  3504.                                             ODTypeToken presentation,
  3505.                                             ODBoolean isOverlaid)
  3506. {
  3507.     // Create a new content shape for the new frame
  3508.     // Grant any shape, for the time being
  3509.     ODRgnHandle tODRegion = frameShape->GetQDRegion(ev);
  3510.     Rect shapeBounds = (*tODRegion)->rgnBBox;
  3511.     
  3512.     CEmbeddingShape* newShape = (CEmbeddingShape*)(this->CreateShape(ev, kEmbeddingShape, shapeBounds));
  3513.     THROW_IF_NULL(newShape);
  3514.     
  3515.     // Make a proxy for it
  3516.     CEmbeddedFrameProxy* frameProxy = new CEmbeddedFrameProxy();
  3517.     frameProxy->InitializeEmbeddedFrameProxy(ev, 
  3518.                                 this, 
  3519.                                 newShape, 
  3520.                                 containingFrame, 
  3521.                                 embedPart,
  3522.                                 viewType,
  3523.                                 presentation);                            
  3524.                 
  3525.     THROW_IF_NULL(frameProxy);
  3526.     
  3527.     // Add the proxy to the shape
  3528.     newShape->AddFrameProxy(frameProxy);
  3529.     
  3530.     // Add the shape to the document
  3531.     this->AddShape(ev, newShape);
  3532.     
  3533.     ODFrame* resultFrame = frameProxy->GetFrame(ev);
  3534.     THROW_IF_NULL(resultFrame);
  3535.     
  3536.     // Assign Frame group and sequence IDs
  3537.     
  3538.     // First check to see if the base frame is grouped
  3539.     ODULong tGroup = baseFrame->GetFrameGroup(ev);
  3540.     
  3541.     // If the group is zero, then it is not a part of a group
  3542.     // Create a unique group for the base frame AND the new frame
  3543.     if (tGroup==0L)
  3544.     {
  3545.         // Get new group ID
  3546.         tGroup = this->GetNewGroupID();
  3547.         
  3548.         // Set BOTH frames to this new group
  3549.         baseFrame->SetFrameGroup(ev, tGroup);
  3550.         resultFrame->SetFrameGroup(ev, tGroup);
  3551.         
  3552.         // Since we have created a new group, then it's obvious that the 
  3553.         // base frame is sequence #1 and resultFrame is 2.
  3554.         baseFrame->ChangeSequenceNumber(ev, 1L);
  3555.         resultFrame->ChangeSequenceNumber(ev, 2L);
  3556.     }
  3557.     else
  3558.     // Base frame is already grouped
  3559.     {
  3560.         // Make the newly created frame be in the base frames group
  3561.         resultFrame->SetFrameGroup(ev, tGroup);
  3562.         
  3563.         // Set the sequence number of the frame to the next in the series
  3564.         ODULong sequenceCount = frameProxy->FindNextSequence(ev, tGroup);
  3565.         resultFrame->ChangeSequenceNumber(ev, sequenceCount+1);
  3566.     }
  3567.     
  3568.     return resultFrame;
  3569. }
  3570.  
  3571.  
  3572. //------------------------------------------------------------------------------
  3573. // Method:        InvalidateActiveBorder
  3574. // Origin:        DrawEditor
  3575. //
  3576. // Description:    .
  3577. //
  3578. //------------------------------------------------------------------------------
  3579. void DrawEditor::InvalidateActiveBorder(Environment *ev, ODFrame *frame)
  3580. {
  3581.     if (fActiveBorderShape)
  3582.     {
  3583.         frame->Invalidate(ev, fActiveBorderShape, kODNULL);
  3584.     }
  3585. }
  3586.  
  3587. //------------------------------------------------------------------------------
  3588. // Method:        AdjustBorderShape
  3589. // Origin:        ODPart
  3590. //
  3591. // Description:    .
  3592. //
  3593. //------------------------------------------------------------------------------
  3594. ODShape* DrawEditor::AdjustBorderShape(Environment *ev, 
  3595.                             ODFacet *embeddedFacet, ODShape* borderShape)
  3596. {
  3597.     ODFacet* containingFacet = embeddedFacet->GetContainingFacet(ev);
  3598.     ODCanvas* tBiasCanvas = containingFacet->GetCanvas(ev);
  3599.     
  3600.     // The active border is moving to a new frame
  3601.     // Get rid of our saved copy and return kODNULL to OpenDoc per recipe.
  3602.     if (borderShape == kODNULL)
  3603.     {
  3604.         // OpenDoc appears to be calling us twice in a row with a null bordershape
  3605.         ODReleaseObject(ev,fActiveBorderShape);
  3606.         fActiveBorderShape = kODNULL;
  3607.         
  3608.         this->ClipEmbeddedFacets(ev, containingFacet);
  3609.         return kODNULL;
  3610.     }
  3611.     
  3612.     ODTransform* tTransform = kODNULL;
  3613.     ODShape* tShape = kODNULL;
  3614.     ODShape* adjusted = borderShape->Copy(ev);
  3615.     
  3616.     // Put our copy of the given shape into frame coordinates
  3617.     tTransform = embeddedFacet->AcquireExternalTransform(ev, tBiasCanvas);
  3618.     adjusted->Transform(ev, tTransform);
  3619.     ODReleaseObject(ev,tTransform);
  3620.     
  3621.     // Find the intersection of the adjusted shape and the display facet
  3622.     ODShape* displayShape = containingFacet->GetFrame(ev)->AcquireUsedShape(ev, tBiasCanvas);
  3623.     adjusted->Intersect(ev, displayShape);
  3624.     ODReleaseObject(ev,displayShape);
  3625.     
  3626.     ODFacet* facet = kODNULL;
  3627.     ODBoolean above = kODFalse;
  3628.     
  3629.     COrdListIterator iter(fShapeList);
  3630.     for (CShape* shape = (CShape*)iter.Last();
  3631.          iter.IsNotComplete(); 
  3632.          shape = (CShape*)iter.Previous())
  3633.     {
  3634.         // Clip native content
  3635.         if (shape->GetShapeType()!=kEmbeddingShape)
  3636.         {
  3637.             if (above)
  3638.             {
  3639.                 TempODShape tShape = embeddedFacet->CreateShape(ev);
  3640.                 ODRgnHandle tRegion = shape->GetBoundingRegion();
  3641.                 tShape->SetQDRegion(ev, tRegion);
  3642.                 adjusted->Subtract(ev, tShape);
  3643.             }
  3644.             
  3645.         }
  3646.         else
  3647.         // Clip embedded content
  3648.         {
  3649.             facet = ((CEmbeddingShape*)shape)->GetEmbeddedFacet(ev, containingFacet);
  3650.             
  3651.             if (above)
  3652.             {
  3653.                 tShape = ODCopyAndRelease(ev, facet->GetFrame(ev)->AcquireUsedShape(ev, tBiasCanvas));
  3654.                 tTransform = facet->AcquireExternalTransform(ev, tBiasCanvas);
  3655.                 tShape->Transform(ev, tTransform);
  3656.                 adjusted->Subtract(ev, tShape);
  3657.                 ODReleaseObject(ev,tShape);
  3658.                 ODReleaseObject(ev,tTransform);
  3659.             }
  3660.             else
  3661.                 above = (ODObjectsAreEqual(ev, facet, embeddedFacet));
  3662.         }
  3663.     }
  3664.     
  3665.     if (fActiveBorderShape == kODNULL)
  3666.     {
  3667.         fActiveBorderShape = adjusted->Copy(ev);
  3668.     }
  3669.     
  3670.     // Put adjusted shape into frame coordinates
  3671.     tTransform = embeddedFacet->AcquireExternalTransform(ev, tBiasCanvas);
  3672.     adjusted->InverseTransform(ev, tTransform); 
  3673.     ODReleaseObject(ev,tTransform);
  3674.     
  3675.     this->ClipEmbeddedFacets(ev, containingFacet);
  3676.         
  3677.     return adjusted;
  3678. }
  3679.  
  3680. //------------------------------------------------------------------------------
  3681. // Method:        ClipEmbeddedFacets
  3682. // Origin:        DrawEditor
  3683. //
  3684. // Description:    Iterate over & clip all facets for the given frame.
  3685. //
  3686. //------------------------------------------------------------------------------
  3687.  
  3688. void DrawEditor::ClipEmbeddedFacets(Environment *ev, ODFrame* containingFrame)
  3689. {
  3690.     #ifdef qProfileDrawEditor
  3691.     // $$$$$ DCS Profiling
  3692.     :: ProfilerSetStatus(kODTrue);
  3693.     #endif
  3694.         
  3695.  
  3696.     // Clip embedded facets for all facets of this frame
  3697.     ODFrameFacetIterator* facets = containingFrame->CreateFacetIterator(ev);
  3698.     for (ODFacet* facet = facets->First(ev); facets->IsNotComplete(ev);
  3699.             facet = facets->Next(ev))
  3700.         this->ClipEmbeddedFacets(ev, facet);
  3701.         
  3702.     delete facets;
  3703.     
  3704.     #ifdef qProfileDrawEditor
  3705.     // $$$$$ DCS Profiling
  3706.     :: ProfilerSetStatus(kODFalse);
  3707.     #endif
  3708.         
  3709. }
  3710. //------------------------------------------------------------------------------
  3711. // Method:        ClipEmbeddedFacets
  3712. // Origin:        DrawEditor
  3713. //
  3714. // Description:    Clip content away from facets embedded within the given
  3715. // facet.
  3716. //
  3717. //------------------------------------------------------------------------------
  3718.  
  3719. void DrawEditor::ClipEmbeddedFacets(Environment *ev, ODFacet* containingFacet)
  3720. {
  3721.     SOM_Trace("DrawEditor","ClipEmbeddedFacets");
  3722.  
  3723.     ODCanvas*        tBiasCanvas = containingFacet->GetCanvas(ev);
  3724.     ODGeometryMode    tGeoMode = GetCanvasGeometryMode(ev, tBiasCanvas);
  3725.     ODShape*        workingClip = 
  3726.                 ODCopyAndRelease(ev, containingFacet->AcquireClipShape(ev, tBiasCanvas));
  3727.     THROW_IF_NULL(workingClip);
  3728.             
  3729.     // We can only embed into our main presentation,
  3730.     // so return if this facet doesn't belong to it
  3731.     ODTypeToken presentation = containingFacet->GetFrame(ev)->GetPresentation(ev);
  3732.     if (presentation != gGlobals->fMainPresentation)
  3733.         return;
  3734.     
  3735.     ODFacet*    embeddedFacet = kODNULL;
  3736.     ODShape*     newClipShape = kODNULL;
  3737.     ODShape*     newMaskShape = kODNULL;
  3738.     ODShape*    tShape = containingFacet->CreateShape(ev);
  3739.     ODRgnHandle    tRegion = kODNULL;
  3740.     ODTransform* clipTransform = kODNULL;
  3741.  
  3742.     // Compute the clip by iterating over all content, native and embedded
  3743.     COrdListIterator iter(fShapeList);
  3744.     for (CShape* shape = (CShape*)iter.First();
  3745.          iter.IsNotComplete(); 
  3746.          shape = (CShape*)iter.Next())
  3747.     {
  3748.         // Clip native content
  3749.         if (shape->GetShapeType()!=kEmbeddingShape)
  3750.         {
  3751.             tRegion = shape->GetBoundingRegion();
  3752.             tShape->SetQDRegion(ev, tRegion);
  3753.             workingClip->Subtract(ev, tShape);
  3754.         }
  3755.         else
  3756.         // Clip embedded content
  3757.         {
  3758.             embeddedFacet = ((CEmbeddingShape*)shape)->GetEmbeddedFacet(ev, containingFacet);
  3759.             
  3760.             // Start with the facets FrameShape
  3761.             newClipShape = ODCopyAndRelease(ev, 
  3762.                     embeddedFacet->GetFrame(ev)->AcquireFrameShape(ev, tBiasCanvas));
  3763.             newClipShape->SetGeometryMode(ev, tGeoMode);
  3764.             
  3765.             // Get used shape to obscure underlying facets
  3766.             newMaskShape = ODCopyAndRelease(ev, 
  3767.                         embeddedFacet->GetFrame(ev)->AcquireUsedShape(ev, tBiasCanvas));
  3768.             
  3769.             clipTransform = embeddedFacet->AcquireExternalTransform(ev, tBiasCanvas);
  3770.             
  3771.             // Put into containing frame coordinates
  3772.             newClipShape->Transform(ev, clipTransform); 
  3773.             newClipShape->Intersect(ev, workingClip);
  3774.             
  3775.             // Put into embedded frame coordinates
  3776.             newClipShape->InverseTransform(ev, clipTransform);
  3777.             embeddedFacet->ChangeGeometry(ev, newClipShape, kODNULL, tBiasCanvas);
  3778.             
  3779.             newMaskShape->Transform(ev, clipTransform);
  3780.             workingClip->Subtract(ev, newMaskShape);
  3781.             
  3782.             // Release acquired geometry
  3783.             ODReleaseObject(ev,newClipShape);
  3784.             ODReleaseObject(ev,newMaskShape);
  3785.             ODReleaseObject(ev,clipTransform);
  3786.         }
  3787.     }
  3788.  
  3789.     // Release acquired geometry
  3790.     ODReleaseObject(ev,workingClip);
  3791.     ODReleaseObject(ev,tShape);
  3792. }
  3793.  
  3794.  
  3795.  
  3796. //------------------------------------------------------------------------------
  3797. // Method:        Draw
  3798. // Origin:        ODPart
  3799. //
  3800. // Description:    This method is called when a facet of a part's display
  3801. //                frame intersects the invalidated portion of an OpenDoc
  3802. //                window. The invalidShape parameter passed in is the
  3803. //                portion of the facet which has been invalidated.
  3804. //
  3805. //                The part sets up the drawing environment using a
  3806. //                C++ helper class (CFocusDrawingEnv) and then calls the
  3807. //                appropriate drawing method based on the frame's
  3808. //                viewType.
  3809. //------------------------------------------------------------------------------
  3810.  
  3811. void DrawEditor::Draw( Environment*        ev,
  3812.                        ODFacet*            facet,
  3813.                        ODShape*            invalidShape )
  3814. {
  3815.     SOM_Trace("DrawEditor","Draw");
  3816.  
  3817.     
  3818.     // Focus the port and origin for drawing in our facet.
  3819.     // Note that this instance of the CFocusDrawingEnv class
  3820.     // is being allocated on the stack. When the execution
  3821.     // leaves the scope of this method, the destructor (which
  3822.     // cleans up the drawing environment) is automatically
  3823.     // called.
  3824.     CFocus initiateDrawing(ev, facet, invalidShape);
  3825.         
  3826.     // Check the presentation we are being requested to draw
  3827.     ODTypeToken presentation = facet->GetFrame(ev)->GetPresentation(ev);
  3828.     
  3829.     // If its the main presentation, then check the view type of the
  3830.     // frame and draw it.
  3831.     if (presentation == gGlobals->fMainPresentation)
  3832.     {
  3833.         ODTypeToken view = facet->GetFrame(ev)->GetViewType(ev);
  3834.         
  3835.         if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  3836.             this->DrawIconView(ev, facet);
  3837.         else if ( view == gGlobals->fThumbnailView )
  3838.             this->DrawThumbnailView(ev, facet);
  3839.         else
  3840.             this->DrawFrameView(ev, facet, invalidShape);
  3841.     }
  3842.     
  3843.     // If its one of our palettes then go ahead and draw it,
  3844.     // palettes don't have multiple view types.
  3845.     // Should I not draw palettes if the main frame is viewed
  3846.     // as other than frame ????? DCS
  3847.     else
  3848.     if (presentation == gGlobals->fColorPalette->GetPresentation())
  3849.         gGlobals->fColorPalette->Draw(ev, facet, invalidShape);
  3850.     else
  3851.     if (presentation == gGlobals->fToolPalette->GetPresentation())
  3852.         gGlobals->fToolPalette->Draw(ev, facet, invalidShape);
  3853. }
  3854.  
  3855. //------------------------------------------------------------------------------
  3856. // Method:        DrawGrid
  3857. // Origin:        DrawEditor
  3858. //
  3859. // Description:    This method simply draws a grid pattern in the frame.
  3860. // We assume that we are currently focused when this method is called.
  3861. //
  3862. //------------------------------------------------------------------------------
  3863.  
  3864. void DrawEditor::DrawGrid( Environment*    ev, ODFrame* frame )
  3865. {
  3866.     SOM_Trace("DrawEditor","DrawGrid");
  3867.  
  3868.     ODShape*    frameShape;
  3869.     RgnHandle    frameRgn;
  3870.     Rect        frameRect;
  3871.     
  3872.     // Grid Pattern
  3873.     // Pattern vertical = {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  3874.     Pattern vertical = {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  3875.     Pattern horizontal = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
  3876.     
  3877.     // Grid Size, color
  3878.     const ODSShort kGridSize = 72;
  3879.     const ODSShort kGridColor = 162;
  3880.     
  3881.     // Get frame bounds for drawing.
  3882.     frameShape = frame->AcquireFrameShape(ev, kODNULL);
  3883.     frameRgn = frameShape->GetQDRegion(ev);
  3884.     frameRect = (*frameRgn)->rgnBBox;
  3885.  
  3886.     // Get the bounds we are drawing into
  3887.     ODSShort minY = frameRect.top;
  3888.     ODSShort maxY = frameRect.bottom;
  3889.     ODSShort minX = frameRect.left;
  3890.     ODSShort maxX = frameRect.right;
  3891.  
  3892.     // Save state
  3893.     PenState tPen;
  3894.     RGBColor tColor;
  3895.     GetPenState(&tPen);
  3896.     GetForeColor(&tColor);
  3897.     
  3898.     // Set the pen for the vertical pattern
  3899.     PenPat(&vertical);
  3900.     
  3901.     // Set the grid color
  3902.     CRGBColor color;
  3903.     gGlobals->fColorPalette->GetColor(kGridColor, &color);
  3904.     RGBForeColor((RGBColor*)&color);
  3905.     
  3906.     // Draw the vertical lines
  3907.     for (ODSShort x = minX; x <= maxX; x += kGridSize)
  3908.     {
  3909.         MoveTo(x,minY);
  3910.         LineTo(x,maxY);
  3911.     }
  3912.     
  3913.     // Set the pen for the horizontal pattern
  3914.     PenPat(&horizontal);
  3915.     
  3916.     // Draw the horizontal lines
  3917.     for (ODSShort y = minY; y <= maxY; y += kGridSize)
  3918.     {
  3919.         MoveTo(minX,y);
  3920.         LineTo(maxX,y);
  3921.     }
  3922.  
  3923.     // Restore state
  3924.     RGBForeColor(&tColor);
  3925.     SetPenState(&tPen);
  3926.     
  3927.     ODReleaseObject(ev,frameShape);
  3928. }
  3929. //------------------------------------------------------------------------------
  3930. // Method:        DrawFrameView
  3931. // Origin:        DrawEditor
  3932. //
  3933. // Description:    This method is called by the part when the frame being
  3934. //                drawn is in "frame" view.
  3935. //
  3936. //                DrawEditor really has not intrisic content. However,
  3937. //                to provide some visual display, we draw the class name
  3938. //                at 80% of the frame's current height using an outlined
  3939. //                font.
  3940. //------------------------------------------------------------------------------
  3941.  
  3942. void DrawEditor::DrawFrameView( Environment*    ev,
  3943.                                 ODFacet*        facet,
  3944.                                 ODShape*         invalidShape )
  3945. {
  3946.     SOM_Trace("DrawEditor","DrawFrameView");
  3947.  
  3948.     ODFrame*    frame;
  3949.     ODSLong        savedRefNum = 0;
  3950.     CFrameInfo*    frameInfo;
  3951.  
  3952.     // If the facet being draw is attached to a source frame in
  3953.     // another window, we need to access the source frame to determine
  3954.     // what size to draw the content.
  3955.     frameInfo = (CFrameInfo*) facet->GetFrame(ev)->GetPartInfo(ev);
  3956.     if ( frameInfo->HasSourceFrame() )
  3957.         frame = frameInfo->GetSourceFrame();
  3958.     else
  3959.         frame = facet->GetFrame(ev);
  3960.  
  3961.     // Clear the screen
  3962.     GrafPtr thePort;
  3963.     GetPort(&thePort);
  3964.     EraseRect(&thePort->portRect);
  3965.     
  3966.     // If the part is selected, fill the background with
  3967.     // the highlight color.
  3968.     if ( facet->GetHighlight(ev) == kODFullHighlight )
  3969.     {
  3970.         UInt8 mode = LMGetHiliteMode();
  3971.         BitClr(&mode,pHiliteBit);
  3972.         LMSetHiliteMode(mode);
  3973.         InvertRect(&thePort->portRect);
  3974.     }
  3975.     
  3976.     // Draw the grid
  3977.     DrawGrid(ev, frame);
  3978.     
  3979.     // Draw Content, if it falls within the invalid shape
  3980.     COrdListIterator iter(fShapeList);
  3981.     for (CShape* shape = (CShape*)iter.Last();
  3982.          iter.IsNotComplete(); 
  3983.          shape = (CShape*)iter.Previous())
  3984.     {
  3985.         ODShape* updateShape = invalidShape->Copy(ev);
  3986.         
  3987.         shape->GetUpdateShape(ev, updateShape);
  3988.         
  3989.         updateShape->Intersect(ev, invalidShape);
  3990.         
  3991.         if (!updateShape->IsEmpty(ev))
  3992.         {
  3993.             shape->DrawShape(ev, facet);
  3994.         }
  3995.     
  3996.         ODReleaseObject(ev, updateShape);
  3997.     }
  3998. }
  3999.  
  4000. //------------------------------------------------------------------------------
  4001. // Method:        DrawIconView
  4002. // Origin:        DrawEditor
  4003. //
  4004. // Description:    This method is called by the part when the frame being
  4005. //                drawn is in "standard icon" view.
  4006. //
  4007. //                The part uses the Icon Utilities toolbox manager to
  4008. //                aid in drawing icons in active windows. The Guidelines
  4009. //                require a different appearance for selected icons in
  4010. //                inactive windows, which we do manually.
  4011. //------------------------------------------------------------------------------
  4012.  
  4013. void DrawEditor::DrawIconView( Environment*        ev,
  4014.                                ODFacet*            facet )
  4015. {
  4016.     SOM_Trace("DrawEditor","DrawIconView");
  4017.  
  4018.     Rect                iconRect;
  4019.     IconTransformType     transformType = ttNone;
  4020.     CFrameInfo*            frameInfo;
  4021.     ODFrame*            frame; 
  4022.     ODTypeToken            viewType;
  4023.     
  4024.     frame        = facet->GetFrame(ev);
  4025.     viewType    = frame->GetViewType(ev);
  4026.     frameInfo     = (CFrameInfo*) frame->GetPartInfo(ev);
  4027.     
  4028.     // Check to see if the facet is selected
  4029.     if ( facet->GetHighlight(ev) == kODFullHighlight )
  4030.         transformType = ttSelected;
  4031.     
  4032.     // Check to see if the frame has been opened into a part window.
  4033.     if ( frameInfo->HasPartWindow() &&
  4034.          frameInfo->GetPartWindow()->IsShown(ev) )
  4035.         transformType |= ttOpen;
  4036.     
  4037.     // Draw the icon.
  4038.     if ( viewType == gGlobals->fLargeIconView )
  4039.         SetRect(&iconRect, 0, 0, kODLargeIconSize, kODLargeIconSize);
  4040.     else // ( viewType == gGlobals->fSmallIconView )
  4041.         SetRect(&iconRect, 0, 0, kODSmallIconSize, kODSmallIconSize);
  4042.  
  4043.     CUsingLibraryResources res;
  4044.     PlotIconID(&iconRect, atAbsoluteCenter, transformType, kDocumentIcons);
  4045. }
  4046.  
  4047. //------------------------------------------------------------------------------
  4048. // Method:        DrawThumbnailView
  4049. // Origin:        DrawEditor
  4050. //
  4051. // Description:    This method is called by the part when the frame being
  4052. //                drawn is in "thumbnail" view.
  4053. //
  4054. //                The part uses a picture for its thumbnail view because
  4055. //                it has no intrinsic content. A picture resource is
  4056. //                probably not sufficient for parts with real content.
  4057. //------------------------------------------------------------------------------
  4058.  
  4059. void DrawEditor::DrawThumbnailView( Environment*    ev,
  4060.                                     ODFacet*        /*facet*/ )
  4061. {
  4062.     SOM_Trace("DrawEditor","DrawThumbnailView");
  4063.  
  4064.     ::LoadThumbnail(ev, &gGlobals->fThumbnail);
  4065.     
  4066.     Rect bounds = (**(PicHandle) gGlobals->fThumbnail).picFrame;
  4067.     
  4068.     OffsetRect(&bounds, -bounds.left, -bounds.top);
  4069.     DrawPicture((PicHandle) gGlobals->fThumbnail, &bounds);
  4070. }
  4071.  
  4072. //------------------------------------------------------------------------------
  4073. // Method:        GeometryChanged
  4074. // Origin:        ODPart
  4075. //
  4076. // Description:    This method is called when the ExternalTransform or
  4077. //                ClipShape of a facet on one this part's display frames
  4078. //                changes.
  4079. //------------------------------------------------------------------------------
  4080.  
  4081. void DrawEditor::GeometryChanged( Environment*    ev,
  4082.                                   ODFacet*        facet,
  4083.                                   ODBoolean        clipShapeChanged,
  4084.                                   ODBoolean        /*externalTransformChanged*/ )
  4085. {
  4086.     SOM_Trace("DrawEditor","GeometryChanged");
  4087.  
  4088.     if ( clipShapeChanged )
  4089.         // Specifying kODNULL means to invalidate the clipShape (which was
  4090.         // calculated from the usedShape).
  4091.         facet->Invalidate(ev, kODNULL, kODNULL);
  4092.         
  4093. // do I NEED this?
  4094. //    this->ClipEmbeddedFacets(ev, facet);  // extra work, but gives correct display
  4095. }
  4096.  
  4097. //------------------------------------------------------------------------------
  4098. // Method:        HighlightChanged
  4099. // Origin:        ODPart
  4100. //
  4101. // Description:    This method is called when a facet....
  4102. //------------------------------------------------------------------------------
  4103.  
  4104. void DrawEditor::HighlightChanged(Environment* ev, ODFacet* facet)
  4105. {
  4106.     ODFrame* frame = facet->GetFrame(ev);
  4107.     
  4108.     // The frame view has no "special" drawing characteristics
  4109.     // when opened or selected, so we don't need to update our
  4110.     // content.
  4111.     
  4112.     if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  4113.         frame->Invalidate(ev, kODNULL, kODNULL);
  4114.         
  4115.     // But we DO need to notify the embedded facets (if any) of the change
  4116.     ODFacetIterator* tIterator = facet->CreateFacetIterator(ev, 
  4117.                                                     kODChildrenOnly, kODFrontToBack);
  4118.     ODHighlight tHighlight = facet->GetHighlight(ev);
  4119.     for ( ODFacet* embeddedFacet = tIterator->First(ev);
  4120.                            tIterator->IsNotComplete(ev);
  4121.           embeddedFacet = tIterator->Next(ev) )
  4122.     {
  4123.         ::ChangeFacetHighlight(ev, embeddedFacet, tHighlight);
  4124.     }
  4125. }
  4126.  
  4127. //------------------------------------------------------------------------------
  4128. // Method:        BeginRelinquishFocus
  4129. // Origin:        ODPart
  4130. //
  4131. // Description:    This method is called when another part (or possibly
  4132. //                ourself) is requesting a focus for one of its display
  4133. //                frames. Returning true means we are willing to give
  4134. //                up the requested focus.
  4135. //
  4136. //                The part willingly gives up any focus unless it is the
  4137. //                modal focus which we don't want to give up until we
  4138. //                are completely done displaying a modal dialog.
  4139. //------------------------------------------------------------------------------
  4140.  
  4141. ODBoolean DrawEditor::BeginRelinquishFocus( Environment*    ev,
  4142.                                             ODTypeToken        focus,
  4143.                                             ODFrame*        /*ownerFrame*/,
  4144.                                             ODFrame*        proposedFrame )
  4145. {
  4146.     SOM_Trace("DrawEditor","BeginRelinquishFocus");
  4147.  
  4148.     ODBoolean willRelinquish = kODTrue;
  4149.  
  4150.     // If the frame that is requesting the selection focus is IN our selection
  4151.     // then close the current selection.
  4152.     if ( focus == gGlobals->fSelectionFocus )
  4153.     {
  4154.         
  4155.         // Is the proposed frame one of our embedded frames?
  4156.         // If so, is it selected?
  4157.         CShape* tShape = this->ShapeForFrame(ev, proposedFrame);
  4158.         if (tShape && tShape->IsSelected())
  4159.         {
  4160.             fSelection->CloseSelection(ev);
  4161.         }
  4162.     }
  4163.                 
  4164.     // Another part is trying to put up a Modal dialog while we
  4165.     // are currently displaying ours. Deny the request.
  4166.     if ( focus == gGlobals->fModalFocus )
  4167.     {
  4168.         ODPart* proposedPart = proposedFrame->AcquirePart(ev);
  4169.         if ( ODObjectsAreEqual(ev, proposedPart, GetODPart()) == kODFalse )
  4170.             willRelinquish = kODFalse;
  4171.         ODReleaseObject(ev, proposedPart);
  4172.     }
  4173.                 
  4174.     return willRelinquish;
  4175. }
  4176.  
  4177. //------------------------------------------------------------------------------
  4178. // Method:        CommitRelinquishFocus
  4179. // Origin:        ODPart
  4180. //
  4181. // Description:    This method is called when it is actually time to give
  4182. //                up a focus that had been requested by another part (or
  4183. //                possibly ourself).
  4184. //
  4185. //                The part calls its FocusLost method to handle the 
  4186. //                "reliquishing" of the particular focus.
  4187. //------------------------------------------------------------------------------
  4188.  
  4189. void DrawEditor::CommitRelinquishFocus( Environment*    ev,
  4190.                                         ODTypeToken        focus,
  4191.                                         ODFrame*        ownerFrame,
  4192.                                         ODFrame*        /*proposedFrame*/ )
  4193. {
  4194.     SOM_Trace("DrawEditor","CommitRelinquishFocus");
  4195.  
  4196.     // We agreed to give up our FocusSet and now we are being asked to
  4197.     // do so.
  4198.     this->FocusLost(ev, focus, ownerFrame);
  4199. }
  4200.  
  4201. //------------------------------------------------------------------------------
  4202. // Method:        AbortRelinquishFocus
  4203. // Origin:        ODPart
  4204. //
  4205. // Description:    This method is called when another part (or possibly
  4206. //                ourself) requested a focus for one of its display
  4207. //                frames, but we returned kODFalse from
  4208. //                BeginRelinqishFocus for one, or all, of the requested
  4209. //                focus. At this point, we are being told to resume
  4210. //                ownership of the focus.
  4211. //
  4212. //                The part calls its FocusAcquired method to handle the 
  4213. //                re-"acquisition" of the particular focus.
  4214. //------------------------------------------------------------------------------
  4215.  
  4216. void DrawEditor::AbortRelinquishFocus( Environment*        ev,
  4217.                                        ODTypeToken        /*focus*/,
  4218.                                        ODFrame*            /*ownerFrame*/,
  4219.                                        ODFrame*            /*proposedFrame*/ )
  4220. {
  4221.     SOM_Trace("DrawEditor","AbortRelinquishFocus");
  4222.  
  4223.     // Some parts may have suspended some events in the BeginRelinquishFocus
  4224.     // method. If so, they would resume those events here.
  4225. }
  4226.  
  4227. //------------------------------------------------------------------------------
  4228. // Method:        FocusAcquired
  4229. // Origin:        ODPart
  4230. //
  4231. // Description:    This method is called when the Arbitrator has
  4232. //                registered us as the "owner" of the particular focus.
  4233. //                This can occur if a focus is requested, or if a focus
  4234. //                is transfered to one of the part's display frames.
  4235. //
  4236. //                The part will display the menu bar when the menu focus
  4237. //                is acquired, and mark a frame active if the selection
  4238. //                focus is acquired.
  4239. //------------------------------------------------------------------------------
  4240.  
  4241. void DrawEditor::FocusAcquired( Environment*    ev,
  4242.                                 ODTypeToken        focus,
  4243.                                 ODFrame*        ownerFrame )
  4244. {
  4245.     SOM_Trace("DrawEditor","FocusAcquired");
  4246.  
  4247.     ODArbitrator* arbitrator =  this->GetSession(ev)->GetArbitrator(ev);
  4248.     
  4249.     if ( focus == gGlobals->fMenuFocus )
  4250.     {
  4251.         if ( arbitrator->RequestFocus(ev, gGlobals->fSelectionFocus, ownerFrame))
  4252.         {
  4253.             this->PartActivated(ev, ownerFrame);
  4254.         }
  4255.     }
  4256.     else if ( focus == gGlobals->fSelectionFocus )
  4257.     {
  4258.         if ( arbitrator->RequestFocus(ev, gGlobals->fMenuFocus, ownerFrame) )
  4259.         {
  4260.             this->PartActivated(ev, ownerFrame);
  4261.         }
  4262.     }
  4263. }
  4264.  
  4265. //------------------------------------------------------------------------------
  4266. // Method:        FocusLost
  4267. // Origin:        ODPart
  4268. //
  4269. // Description:    This method is called when the Arbitrator has
  4270. //                unregistered us as the "owner" of the particular
  4271. //                focus.
  4272. //
  4273. //                The part unmarks the active frame if the selection
  4274. //                focus is lost.
  4275. //------------------------------------------------------------------------------
  4276.  
  4277. void DrawEditor::FocusLost( Environment*    ev,
  4278.                             ODTypeToken        focus,
  4279.                             ODFrame*        ownerFrame )
  4280. {
  4281.     SOM_Trace("DrawEditor","FocusLost");
  4282.  
  4283.     if ( focus == gGlobals->fSelectionFocus )
  4284.     {
  4285.         // Mark the frame as inactive
  4286.         CFrameInfo* frameInfo = (CFrameInfo*) ownerFrame->GetPartInfo(ev);
  4287.         frameInfo->SetFrameActive(kODFalse);
  4288.         
  4289.         // Only hide the palettes if a part other than "us" requested
  4290.         // the focus. This will prevent flash in the case where there
  4291.         // are multiple DrawEditors embedded inside a document.
  4292.         if (!gGlobals->fDrawEditorRequestingFocus)
  4293.         {
  4294.             // Hide our palettes
  4295.             if (gGlobals->fToolPalette->IsShown(ev))
  4296.                 gGlobals->fToolPalette->ShowPalette(ev, kODFalse);
  4297.             if (gGlobals->fColorPalette->IsShown(ev))
  4298.                 gGlobals->fColorPalette->ShowPalette(ev, kODFalse);
  4299.         }
  4300.         
  4301.         // Reset flag
  4302.         gGlobals->fDrawEditorRequestingFocus = kODFalse;
  4303.     }
  4304. }
  4305.  
  4306.  
  4307. //------------------------------------------------------------------------------
  4308. // Method:        RelinquishAllFoci
  4309. // Origin:        DrawEditor
  4310. //
  4311. // Description:    This method relinquishes all foci for the given frame.
  4312. //------------------------------------------------------------------------------
  4313.  
  4314. void DrawEditor::RelinquishAllFoci(Environment* ev, ODFrame* frame)
  4315. {
  4316.         ODArbitrator* arbitrator = GetODPart()->GetStorageUnit(ev)
  4317.                                     ->GetSession(ev)->GetArbitrator(ev);
  4318.         
  4319.         // Make sure the frame going away does not own any foci. Forgetting
  4320.         // to do this, will cause a "refcounting" error when the frame
  4321.         // is deleted by the draft.
  4322.         
  4323.         TRY
  4324.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fKeyFocus);
  4325.         if (focusFrame!=kODNULL)
  4326.         {
  4327.             if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  4328.             {
  4329.                 arbitrator->RelinquishFocus(ev, gGlobals->fKeyFocus, frame);
  4330.                 this->FocusLost(ev, gGlobals->fKeyFocus, frame);
  4331.             }
  4332.         }
  4333.         CATCH_ALL
  4334.         ENDTRY
  4335.         
  4336.         TRY
  4337.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fClipboardFocus);
  4338.         if (focusFrame!=kODNULL)
  4339.         {
  4340.             if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  4341.             {
  4342.                 arbitrator->RelinquishFocus(ev, gGlobals->fClipboardFocus, frame);
  4343.                 this->FocusLost(ev, gGlobals->fClipboardFocus, frame);
  4344.             }
  4345.         }
  4346.         CATCH_ALL
  4347.         ENDTRY
  4348.  
  4349.         TRY
  4350.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fSelectionFocus);
  4351.         if (focusFrame!=kODNULL)
  4352.         {
  4353.             if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  4354.             {
  4355.                 arbitrator->RelinquishFocus(ev, gGlobals->fSelectionFocus, frame);
  4356.                 this->FocusLost(ev, gGlobals->fSelectionFocus, frame);
  4357.             }
  4358.         }
  4359.         CATCH_ALL
  4360.         ENDTRY
  4361.         
  4362.         TRY
  4363.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
  4364.         if (focusFrame!=kODNULL)
  4365.         {
  4366.             if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  4367.             {
  4368.                 arbitrator->RelinquishFocus(ev, gGlobals->fMenuFocus, frame);
  4369.                 this->FocusLost(ev, gGlobals->fMenuFocus, frame);
  4370.             }
  4371.         }
  4372.         CATCH_ALL
  4373.         ENDTRY
  4374. }
  4375.  
  4376.  
  4377.  
  4378. //------------------------------------------------------------------------------
  4379. // Method:        PartActivated
  4380. // Origin:        DrawEditor
  4381. //
  4382. // Description:    This method is called when the part has successfully acquired
  4383. //                the set of foci which allow it to "run".
  4384. //------------------------------------------------------------------------------
  4385.  
  4386. void DrawEditor::PartActivated( Environment*    ev,
  4387.                                      ODFrame*        frame )
  4388. {
  4389.     SOM_Trace("DrawEditor","PartActivated");
  4390.     
  4391.     // We are required to re-validate the menubar before displaying it because
  4392.     // any part can/could swap the base menubar at any time.
  4393.     if ( gGlobals->fMenuBar->IsValid(ev) == kODFalse )
  4394.     {
  4395.         ODReleaseObject(ev, gGlobals->fMenuBar);
  4396.         
  4397.         ODMenuBar* tMenuBar = ODGetSession(ev,frame)->GetWindowState(ev)->CopyBaseMenuBar(ev);
  4398.         
  4399.         #ifdef ODDebug
  4400.         if (tMenuBar==kODNULL)
  4401.             DebugStr("\pCopyBaseMenuBar returned NULL menu bar!");
  4402.         #endif
  4403.         
  4404.         gGlobals->fMenuBar = tMenuBar;
  4405.         
  4406.         // After copying the "new" base menu bar, don't forget to re-install
  4407.         // your part's menus.
  4408.         this->LoadMenus(ev);
  4409.     }
  4410.         
  4411.     // Display our menu bar.
  4412.     gGlobals->fMenuBar->Display(ev);
  4413.     
  4414.     // And set our "active" state.
  4415.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  4416.     frameInfo->SetFrameActive(kODTrue);
  4417.  
  4418.         // If we got the focus from some other part then are
  4419.         // palettes are hidded, show them.
  4420.         // Show our palettes
  4421.         if (gGlobals->fShowColorPalette)
  4422.             gGlobals->fColorPalette->ShowPalette(ev, kODTrue);
  4423.         if (gGlobals->fShowToolPalette)
  4424.             gGlobals->fToolPalette->ShowPalette(ev, kODTrue);
  4425.     
  4426.         // Reset flag, we are no longer requesting focus
  4427.         gGlobals->fDrawEditorRequestingFocus = kODFalse;
  4428. }
  4429.  
  4430.  
  4431. //------------------------------------------------------------------------------
  4432. // Method:        ActivateFrame
  4433. // Origin:        DrawEditor
  4434. //
  4435. // Description:    This method is called by the part when a kODEvtMouseUp
  4436. //                occurs in an inactive frame in an active window, and
  4437. //                when an OpenDoc document comes forward.
  4438. //
  4439. //                The part activates the frame by requesting the
  4440. //                UIFocusSet (created in Initialize) and by calling
  4441. //                FocusAcquired if we were successful. The method
  4442. //                returns true if no problems were encountered as a
  4443. //                signal to the caller that the frame is now "active".
  4444. //------------------------------------------------------------------------------
  4445.  
  4446. ODBoolean DrawEditor::ActivateFrame( Environment*    ev,
  4447.                                      ODFrame*        frame )
  4448. {
  4449.     SOM_Trace("DrawEditor","ActivateFrame");
  4450.  
  4451.     // only activate frames that are in the main presentation
  4452.     ODTypeToken presentation = frame->GetPresentation(ev);
  4453.     if (presentation == gGlobals->fMainPresentation)
  4454.     {
  4455.         // Remember that we are requesting focus
  4456.         // So that if we already have the focus we 
  4457.         // won't hide our palettes, thus preventing flash
  4458.         gGlobals->fDrawEditorRequestingFocus = kODTrue;
  4459.         
  4460.         // Request the set of foci necessary to become active.
  4461.         if ( this->GetSession(ev)->GetArbitrator(ev)->
  4462.                     RequestFocusSet(ev, gGlobals->fUIFocusSet, frame))
  4463.         {
  4464.             this->PartActivated(ev, frame);
  4465.         }
  4466.         else
  4467.             // We were unable to acquire the foci we need to be active.
  4468.             return kODFalse;
  4469.     }
  4470.     else
  4471.         // Cannot activate frames not in the main presentation.
  4472.         return kODFalse;
  4473.     
  4474.     // We sucessfully acquired the foci we need to be active.
  4475.     return kODTrue;
  4476. }
  4477.  
  4478. //------------------------------------------------------------------------------
  4479. // Method:        WindowActivating
  4480. // Origin:        DrawEditor
  4481. //
  4482. // Description:    This method is called by the part when a process
  4483. //                switch event (kODEvtOS) occurs.
  4484. //
  4485. //                The part remembers the frame's active state and restores it when
  4486. //                events come in. If the frame is active and the window is being
  4487. //                sent into the background, remember to reactivate the part when
  4488. //                the window is reactivated.
  4489. //------------------------------------------------------------------------------
  4490.  
  4491. void DrawEditor::WindowActivating( Environment*        ev,
  4492.                                    ODFrame*            frame,
  4493.                                    ODBoolean        activating )
  4494. {
  4495.     SOM_Trace("DrawEditor","WindowActivating");
  4496.  
  4497.     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  4498.     
  4499.     // Check the presentation of the frame
  4500.     // Make sure it is the main presentation
  4501.     ODTypeToken presentation = frame->GetPresentation(ev);
  4502.     if (presentation == gGlobals->fMainPresentation)
  4503.     {
  4504.         ODBoolean checkPalettes = kODFalse;
  4505.  
  4506.     // The window is being activated and we had the selection focus when
  4507.     // the window was deactivated, so activate ourself.
  4508.         if ( activating && frameInfo->FrameNeedsReactivating() )
  4509.         {
  4510.             this->ActivateFrame(ev, frame);
  4511.             frameInfo->SetFrameReactivate(kODFalse);
  4512.             checkPalettes = kODTrue;
  4513.         }
  4514.         // The window is being deactivated and we have the active part.
  4515.         // So give up our foci and remind ourselves that we need to request
  4516.         // the focus when the window is reactivated.
  4517.         else if ( !activating && frameInfo->IsFrameActive() )
  4518.         {
  4519.             frameInfo->SetFrameReactivate(kODTrue);
  4520.             checkPalettes = kODTrue;
  4521.         }
  4522.     
  4523.         if ( checkPalettes )
  4524.         {
  4525.             // Show / Hide Palettes
  4526.             if (gGlobals->fShowToolPalette)
  4527.                 gGlobals->fToolPalette->ShowPalette(ev, activating);
  4528.             if (gGlobals->fShowColorPalette)
  4529.                 gGlobals->fColorPalette->ShowPalette(ev, activating);
  4530.         }
  4531.     
  4532.         // Must set hilite state of selected facets here
  4533.         fSelection->Activate(ev, activating, frame);
  4534.     
  4535.         if (!activating)
  4536.         {
  4537.             ODArbitrator* tArbitrator = this->GetSession(ev)->GetArbitrator(ev);
  4538.             TempODFrame clipboardFocus = tArbitrator->AcquireFocusOwner(ev, gGlobals->fClipboardFocus);
  4539.             if (ODObjectsAreEqual(ev, clipboardFocus, frame))
  4540.                 tArbitrator->RelinquishFocus(ev, gGlobals->fClipboardFocus, frame);
  4541.         }
  4542.     
  4543.     }
  4544.  
  4545. }
  4546.  
  4547. //------------------------------------------------------------------------------
  4548. // Method:        ExecuteCommand
  4549. // Origin:        DrawEditor
  4550. //
  4551. // Description:    This method is called when a command needs to be done for the first time.
  4552. //                
  4553. //
  4554. // Assumptions:    This method assumes that if the command was not undoable that it may
  4555. //                be deleted after it is executed. Undo-able commands get registered with
  4556. //                OpenDoc and connot be deleted until they are committed.
  4557. //------------------------------------------------------------------------------
  4558.  
  4559. void DrawEditor::ExecuteCommand(Environment *ev, CCommand* command)
  4560. {
  4561.     SOM_Trace("DrawEditor","ExecuteCommand");
  4562.  
  4563.     TRY
  4564.         command->DoCommand(ev);            // execute the command
  4565.     
  4566.         if (!command->CanUndo())        // This command was not registered with OpenDoc.
  4567.         {
  4568.             command->Commit(ev, kODDone);
  4569.             delete command;
  4570.         }
  4571.     CATCH_ALL
  4572.         command->AbortCommand(ev);
  4573.         RERAISE;
  4574.     ENDTRY
  4575. }
  4576.  
  4577.  
  4578. //------------------------------------------------------------------------------
  4579. // Method:        UndoAction
  4580. // Origin:        ODPart
  4581. //
  4582. // Description:    This method is called by OpenDoc when a command needs to be undone.
  4583. //                
  4584. //
  4585. //------------------------------------------------------------------------------
  4586.  
  4587. void DrawEditor::UndoAction(Environment *ev, ODActionData* actionState)
  4588. {
  4589.     SOM_Trace("DrawEditor","UndoAction");
  4590.  
  4591.     TRY
  4592.         CCommand* undoCommand = *((CCommand**)actionState->_buffer);
  4593.         
  4594.         if (undoCommand==kODNULL)
  4595.             return;
  4596.     
  4597.         undoCommand->UndoCommand(ev);
  4598.     CATCH_ALL
  4599.         ODSetSOMException(ev, kODErrUndefined);
  4600.     ENDTRY
  4601. }
  4602.  
  4603.  
  4604. //------------------------------------------------------------------------------
  4605. // Method:        RedoAction
  4606. // Origin:        ODPart
  4607. //
  4608. // Description:    This method is called by OpenDoc when a command needs to be redone.
  4609. //                
  4610. //
  4611. //------------------------------------------------------------------------------
  4612.  
  4613. void DrawEditor::RedoAction(Environment *ev, ODActionData* actionState)
  4614. {
  4615.     SOM_Trace("DrawEditor","RedoAction");
  4616.  
  4617.     TRY
  4618.         CCommand* redoCommand = *((CCommand**)actionState->_buffer);
  4619.         
  4620.         // Better not be null!
  4621.         if (redoCommand==kODNULL)
  4622.             return;
  4623.         
  4624.         redoCommand->RedoCommand(ev);
  4625.     CATCH_ALL
  4626.         ODSetSOMException(ev, kODErrUndefined);
  4627.     ENDTRY
  4628. }
  4629.  
  4630.  
  4631. //------------------------------------------------------------------------------
  4632. // Method:        DisposeActionState
  4633. // Origin:        DrawEditor
  4634. //
  4635. // Description:    This method is called by OpenDoc when an action has been
  4636. // committed.
  4637. //                
  4638. //
  4639. //------------------------------------------------------------------------------
  4640.  
  4641. void DrawEditor::DisposeActionState(Environment *ev, 
  4642.                                     ODActionData* actionState,
  4643.                                     ODDoneState doneState)
  4644. {
  4645.     SOM_Trace("DrawEditor","DisposeActionState");
  4646.  
  4647.     TRY
  4648.         CCommand* theCommand = *((CCommand**)actionState->_buffer);
  4649.     
  4650.         ODBoolean shouldDeleteCommand = kODTrue;
  4651.         
  4652.         // The command may be null, as in the case of a begin action.
  4653.         // See Command.h
  4654.         if (theCommand)
  4655.         {
  4656.             theCommand->Commit(ev, doneState);
  4657.             
  4658.             if (shouldDeleteCommand)
  4659.                 delete theCommand;
  4660.         }
  4661.         
  4662.     CATCH_ALL
  4663.         ODSetSOMException(ev, kODErrUndefined);
  4664.     ENDTRY
  4665. }
  4666.  
  4667.  
  4668. //------------------------------------------------------------------------------
  4669. // Method:        HandleEvent
  4670. // Origin:        ODPart
  4671. //
  4672. // Description:    The method is called when an event, which falls into
  4673. //                the category of an owned focus, occurs. The two
  4674. //                exceptions to this are "mouse movement" events and 
  4675. //                embedded frame events, which can occur when a part
  4676. //                owns no foci.
  4677. //
  4678. //                The part returns true if the event was handled.
  4679. //------------------------------------------------------------------------------
  4680.  
  4681. ODBoolean DrawEditor::HandleEvent( Environment*        ev,
  4682.                                    ODEventData*        event,
  4683.                                    ODFrame*            frame,
  4684.                                    ODFacet*            facet,
  4685.                                    ODEventInfo*        eventInfo )
  4686. {
  4687.     SOM_Trace("DrawEditor","HandleEvent");
  4688.  
  4689.     ODBoolean    eventHandled = kODFalse;
  4690.  
  4691.     // Event handling is basically the same as standard Macintosh applications,
  4692.     // except that the events have been renamed for cross-platform compatability.
  4693.     
  4694.     switch ( event->what )
  4695.     {
  4696.         case kODEvtMouseDown:
  4697.         case kODEvtBGMouseDown :        
  4698.         case kODEvtMouseUpBorder:
  4699.         case kODEvtMouseUp:
  4700.         case kODEvtMouseUpEmbedded:
  4701.         case kODEvtMouseDownEmbedded:
  4702.         case kODEvtBGMouseDownEmbedded :
  4703.             eventHandled = this->HandleMouseEvent(ev, event, facet, eventInfo);
  4704.             break;
  4705.             
  4706.         // Special case
  4707.         case kODEvtMouseDownBorder:
  4708.                 eventHandled = HandleMouseDownInEmbeddedFrameBorder( ev, facet, event, eventInfo );
  4709.             break;
  4710.             
  4711.         case kODEvtMenu:
  4712.             eventHandled = this->HandleMenuEvent(ev, event, frame);
  4713.             break;
  4714.  
  4715.         case kODEvtActivate:
  4716.             // We are being notified that a window we are displayed in has
  4717.             // just been de/activated (un/hilighted).
  4718.             this->WindowActivating(ev, frame, (event->modifiers & activeFlag));
  4719.             eventHandled = kODTrue;
  4720.             break;
  4721.     
  4722.         case kODEvtMouseEnter:
  4723.         case kODEvtMouseLeave:
  4724.             SetCursor(&ODQDGlobals.arrow);
  4725.             eventHandled = kODTrue;
  4726.             break;
  4727.  
  4728.         case kODEvtMouseWithin:
  4729.             eventHandled = kODTrue;
  4730.             break;
  4731.  
  4732.         case kODEvtWindow:
  4733.             eventHandled = HandleWindowEvent(ev, event, frame);
  4734.             break;
  4735.         
  4736.         // Other events a part might handle
  4737.         case kODEvtNull:
  4738.         case kODEvtKeyDown:
  4739.         case kODEvtKeyUp:
  4740.         case kODEvtAutoKey:
  4741.         case kODEvtDisk:
  4742.         case kODEvtOS:
  4743.         
  4744.         default:
  4745.             break;
  4746.     }
  4747.  
  4748.     return eventHandled;
  4749. }
  4750.  
  4751. //------------------------------------------------------------------------------
  4752. // Method:        HandleMenuEvent
  4753. // Origin:        DrawEditor
  4754. //
  4755. // Description:    This method is called by the part when a menu event is
  4756. //                received.
  4757. //
  4758. //                Using the menu bar object, we determine what the menu
  4759. //                command is, and call the appropriate method to handle
  4760. //                it.
  4761. //------------------------------------------------------------------------------
  4762.  
  4763. ODBoolean DrawEditor::HandleMenuEvent( Environment*        ev,
  4764.                                        ODEventData*        event,
  4765.                                        ODFrame*            frame )
  4766. {
  4767.     SOM_Trace("DrawEditor","HandleMenuEvent");
  4768.  
  4769.     ODULong        menuResult    = event->message;
  4770.     ODUShort    menu        = HiWord(menuResult);
  4771.     ODUShort    item        = LoWord(menuResult);
  4772.  
  4773.     ODCommandID commandID =  gGlobals->fMenuBar->GetCommand(ev, menu, item);
  4774.     switch (commandID)
  4775.     {
  4776.         case kODCommandAbout:    
  4777.             this->DoDialogBox(ev, frame, kAboutBoxID);
  4778.             return kODTrue;
  4779.             break;
  4780.  
  4781.         case kODCommandViewAsWin:
  4782.             this->Open(ev, frame);
  4783.             return kODTrue;
  4784.             break;
  4785.  
  4786.         // Clipboard
  4787.         case kODCommandCopy:
  4788.         case kODCommandCut:     
  4789.             return this->DoCutCopy(ev, commandID, frame); 
  4790.             break;
  4791.             
  4792.         case kODCommandPaste:    return this->DoPaste(ev, frame); 
  4793.             break;
  4794.             
  4795.         case kODCommandPasteAs:
  4796.             {
  4797.                 // Get any facet to pass to ShowPasteAsDlg
  4798.                 TempODFrameFacetIterator facets(ev,frame);
  4799.                 return this->DoPasteAs(ev, frame, facets.Current()); 
  4800.             }
  4801.             break;
  4802.             
  4803.         case kODCommandClear:    return this->DoClear(ev, frame); 
  4804.             break;
  4805.             
  4806.         case kODCommandSelectAll: 
  4807.             fSelection->SelectAll(ev, frame); 
  4808.             return kODTrue;
  4809.             break;        
  4810.         
  4811.         // Drawing Commands
  4812.         case kMoveForwardCmd:
  4813.         case kMoveFrontCmd:
  4814.         case kMoveBackwardCmd:
  4815.         case kMoveBackCmd:
  4816.             CMoveShapeCommand* command = new CMoveShapeCommand( this, 
  4817.                                             frame, commandID, fSelection);
  4818.             this->ExecuteCommand(ev, command);
  4819.             return kODTrue;
  4820.             break;
  4821.         
  4822.         case kShowHideToolPaletteCmd:
  4823.             gGlobals->fShowToolPalette = !gGlobals->fShowToolPalette;
  4824.             gGlobals->fToolPalette->ShowPalette( ev, gGlobals->fShowToolPalette);
  4825.             return kODTrue;
  4826.             break;
  4827.         
  4828.         case kShowHideColorPaletteCmd:
  4829.             gGlobals->fShowColorPalette = !gGlobals->fShowColorPalette;
  4830.             gGlobals->fColorPalette->ShowPalette( ev, gGlobals->fShowColorPalette);
  4831.             return kODTrue;
  4832.             break;
  4833.         
  4834.         // This command should only be active in the case where one
  4835.         // embedded shape is selected, or if a Link or Link source is selected.
  4836.         case kODCommandGetPartInfo:
  4837.             {
  4838.                 if (fSelection->IsOneLink())
  4839.                 {
  4840.                     CPublishLink* pLink = (CPublishLink*)fSelection->GetPublishLinks()->First();
  4841.                     if (pLink)
  4842.                         pLink->ShowLinkInfoDialog(ev);
  4843.                     else
  4844.                     {
  4845.                         CSubscribeLink* sLink = (CSubscribeLink*)fSelection->GetSubscribeLinks()->First();
  4846.                         if (!sLink)
  4847.                         {
  4848.                             COrdListIterator iter(fSelection->GetShapeList());
  4849.                             for (CShape* shape = (CShape*)iter.First(); 
  4850.                                                     iter.IsNotComplete(); 
  4851.                                                     shape = (CShape*)iter.Next())
  4852.                             {
  4853.                                 if ((sLink = shape->GetSubscribeLink()) != kODNULL)
  4854.                                     break;
  4855.                             }
  4856.                         }
  4857.                         ASSERT_NOT_NULL(sLink);
  4858.                         
  4859.                         sLink->ShowLinkInfoDialog(ev);
  4860.                     }
  4861.                 }
  4862.                 else
  4863.             {
  4864.                 // Selection should be just one embedded shape
  4865.                 CEmbeddingShape* tShape = fSelection->IsOneEmbeddedShape(ev);
  4866.                 THROW_IF_NULL(tShape);
  4867.                 
  4868.                 // We should always have at least one frame available
  4869.                 // Actually, this could fail if the part is scrolled off screen
  4870.                 // DCS $$$$$
  4871.                 ODFrame* tFrame = tShape->GetAnyFrame(ev);
  4872.                 THROW_IF_NULL(tFrame);
  4873.                 
  4874.                 // Get any facet to pass to ShowPartFrameInfo
  4875.                 TempODFrameFacetIterator facets(ev,tFrame);
  4876.                 ODInfo* info = this->GetSession(ev)->GetInfo(ev);
  4877.                 info->ShowPartFrameInfo( ev, 
  4878.                                          facets.Current(),
  4879.                                         !IsReadOnly());
  4880.                 }
  4881.                 return kODTrue;
  4882.             }
  4883.             break;
  4884.         
  4885.         case kODCommandOpen:
  4886.             this->DoOpen(ev, frame);
  4887.             return kODTrue;
  4888.             break;
  4889.         
  4890.         // Other commands a part might handle
  4891.         case kODCommandInsert:
  4892.         case kODCommandPageSetup:
  4893.         case kODCommandPrint:
  4894.         case kODCommandPreferences:
  4895.             break;
  4896.     
  4897.     }
  4898.         
  4899.     return kODFalse;
  4900. }
  4901.  
  4902. //------------------------------------------------------------------------------
  4903. // Method:        HandleMouseUpActivate
  4904. // Origin:        DrawEditor
  4905. //
  4906. // Description:    This method is called by handlers which respond to mouse ups.
  4907. // Here we will do the necessary work to activate the frame and window, if they
  4908. // are not already active.
  4909. //
  4910. //
  4911. // Remember:    When a frame is inactive, the first mouse up event
  4912. //                should activate it; inactive frames do not recieve
  4913. //                kODEvtMouseDown events.
  4914. //------------------------------------------------------------------------------
  4915.  
  4916. ODBoolean DrawEditor::HandleMouseUpActivate( Environment* ev, ODFacet* facet)
  4917. {
  4918.     ODWindow* window = facet->GetWindow(ev);
  4919.     
  4920.     TRY
  4921.         // Activate inactive windows on the first mouse up event.
  4922.         if ( !window->IsActive(ev) )
  4923.             window->Select(ev);
  4924.         // Activate the frame (if needed) on all subsequent mouse up events.
  4925.         else
  4926.         {
  4927.             ODFrame* frame = facet->GetFrame(ev);
  4928.             
  4929.             // Get our state information from the PartInfo of the frame.
  4930.             CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  4931.                             
  4932.             // If this frame is not the active one, activate it by requesting
  4933.             // the appropriate foci.
  4934.     
  4935.             if ( !frameInfo->IsFrameActive() )
  4936.             {
  4937.                 if ( this->ActivateFrame(ev, frame) )
  4938.                 {
  4939.                     // Keep track of which facet was the last active for positioning
  4940.                     // child windows.
  4941.                     frameInfo->SetActiveFacet(facet);
  4942.                 }
  4943.                 else
  4944.                     // We were unable to acquire the necessary focus and activate it.
  4945.                     return kODFalse;
  4946.             }
  4947.         }
  4948.     CATCH_ALL
  4949.         return kODFalse;
  4950.     ENDTRY
  4951.     
  4952.     return kODTrue;
  4953. }
  4954.  
  4955.  
  4956. //------------------------------------------------------------------------------
  4957. // Method:        HandleMouseEvent
  4958. // Origin:        DrawEditor
  4959. //
  4960. // Description:    This method is called by the part when a mouse event
  4961. //                is recieved.
  4962. //
  4963. //                A typical part would determine the event type(up/down)
  4964. //                and respond appropriately, but we have no "real"
  4965. //                content model, so we activate the part as appropriate
  4966. //                and call a generic method to handle the event.
  4967. //
  4968. // Remember:    When a frame is inactive, the first mouse up event
  4969. //                should activate it; inactive frames do not recieve
  4970. //                kODEvtMouseDown events.
  4971. //------------------------------------------------------------------------------
  4972.  
  4973. ODBoolean DrawEditor::HandleMouseEvent( Environment*    ev,
  4974.                                         ODEventData*    event,
  4975.                                         ODFacet*        facet,
  4976.                                         ODEventInfo*    eventInfo )
  4977. {
  4978.     SOM_Trace("DrawEditor","HandleMouseEvent");
  4979.  
  4980.     if ( facet != kODNULL )
  4981.     {
  4982.         switch ( event->what)
  4983.         {
  4984.         case kODEvtMouseUp :
  4985.         case kODEvtMouseUpEmbedded:
  4986.         case kODEvtMouseUpBorder:
  4987.                 this->HandleMouseUpActivate(ev, facet);
  4988.                 return kODTrue;
  4989.                 break;
  4990.                 
  4991.         case kODEvtMouseDownEmbedded:
  4992.         case kODEvtBGMouseDownEmbedded :    
  4993.                 return HandleMouseDownInEmbeddedFrame( ev, facet, event, eventInfo );
  4994.                 break;
  4995.                 
  4996.         case kODEvtMouseDown :        
  4997.         case kODEvtBGMouseDown :        
  4998.             // Handle the mouse down event.
  4999.             this->HandleMouseDown(ev, facet, event, eventInfo);
  5000.             return kODTrue;
  5001.             break;
  5002.             
  5003.         case kODEvtMouseDownBorder:
  5004.             return HandleMouseDownInEmbeddedFrameBorder( ev, facet, event, eventInfo );
  5005.             return kODTrue;
  5006.             break;
  5007.         
  5008.             // Always handles event
  5009.             return kODTrue;
  5010.         default:
  5011.             return kODFalse;
  5012.         }
  5013.     }
  5014.     else
  5015.     {
  5016.         // User clicked outside the bounds of a Modal window.
  5017.         
  5018.         SysBeep(1);
  5019.         return kODTrue;
  5020.     }
  5021.  
  5022.     return kODFalse;
  5023. }
  5024.  
  5025. //------------------------------------------------------------------------------
  5026. // Method:        HandleWindowEvent
  5027. // Origin:        DrawEditor
  5028. //
  5029. // Description:    This method is called by the part to handle window events.
  5030. //------------------------------------------------------------------------------
  5031.  
  5032. ODBoolean DrawEditor::HandleWindowEvent( Environment*    ev,
  5033.                                          ODEventData*    event,
  5034.                                             ODFrame*        frame )
  5035. {
  5036.     ODBoolean handled = kODFalse;
  5037.     
  5038.     switch ( event->message )
  5039.     {
  5040.         case inGoAway:
  5041.             // If the frame belonged to one of our palettes, then
  5042.             // change the show flag.
  5043.             ODTypeToken presentation = frame->GetPresentation(ev);
  5044.             if (presentation == gGlobals->fColorPalette->GetPresentation())
  5045.             {
  5046.                 gGlobals->fShowColorPalette = kODFalse;
  5047.             }
  5048.             else
  5049.             if (presentation == gGlobals->fToolPalette->GetPresentation())
  5050.             {
  5051.                 gGlobals->fShowToolPalette = kODFalse;
  5052.             }
  5053.             break;
  5054.         
  5055.         default: ;
  5056.     }
  5057.     
  5058.     return handled;
  5059. }
  5060.  
  5061. //------------------------------------------------------------------------------
  5062. // Method:        HandleSelection
  5063. // Origin:        DrawEditor
  5064. //
  5065. // Description:    This method is called by HandleMouseDown to handle selection with
  5066. //                the mouse.
  5067. //------------------------------------------------------------------------------
  5068.  
  5069. ODBoolean DrawEditor::HandleSelection( Environment*    ev,
  5070.                                 ODFacet*        facet,
  5071.                                 ODEventData*    event,
  5072.                                 ODEventInfo*    eventInfo)
  5073. {
  5074.     // Get the localized mouse coordinates from the Event Info.
  5075.     Point where;
  5076.     where.h = FixedToInt(eventInfo->where.x);
  5077.     where.v = FixedToInt(eventInfo->where.y);
  5078.     
  5079.     // Did the user click in a shape handle?
  5080.     short whichHandle;
  5081.     CShape* shape = fSelection->WhichHandle(ev, facet, where, &whichHandle);
  5082.     if (shape != kODNULL)
  5083.     {
  5084.         if (this->IsReadOnly())
  5085.         {
  5086.             SysBeep(1);
  5087.             return kODTrue;
  5088.         }
  5089.         
  5090.         CSubscribeLink* link = kODNULL;
  5091.         if (fLinkStatus == kODInLinkDestination  || !fSelection->CanEditSelectedContent(link))
  5092.             this->EditInLink(ev, link);
  5093.     
  5094.         // We havn't tracked the drag, so can't complete the users action if the link was broken
  5095.         // in response to the dialog
  5096.         else
  5097.             fSelection->Resize(ev, shape, facet, whichHandle, event);
  5098.         
  5099.         return kODTrue;
  5100.     }
  5101.     
  5102.     // if not in a handle, look for a shape
  5103.     shape = this->WhichShape(ev, where);
  5104.     
  5105.     // If the user did not click in a shape then we must begin tracking a selection
  5106.     // and select some shapes. There is code in the selection class to do this.
  5107.     if (shape == kODNULL)
  5108.     {
  5109.         // Have the selection track the mouse and ( possibly ) select shapes.
  5110.         fSelection->SelectWithRectangle(ev, facet, event);
  5111.     
  5112.         // Must call our activate code here since the lasso consumes the mouse
  5113.         // up event.
  5114.         this->HandleMouseUpActivate(ev, facet);
  5115.     }
  5116.     else
  5117.     {
  5118.         // The user clicked in a shape. Either extend or change the selection.
  5119.         // Again, the selection class has code for modifying the selection in
  5120.         // this case.
  5121.         fSelection->SelectWithShape(ev, facet, event, shape);
  5122.     }
  5123.  
  5124.     return kODTrue;
  5125. }
  5126.  
  5127. //------------------------------------------------------------------------------
  5128. // Method:        DropCompleted
  5129. // Origin:        ODPart
  5130. //
  5131. // Description:    This method may be called by OpenDoc when an asynchronous
  5132. // drop is completed. I also call this method from my DropShape command to 
  5133. // turn off drag hiliting.
  5134. //------------------------------------------------------------------------------
  5135.  
  5136. void DrawEditor::DropCompleted(Environment *ev, ODPart* part, ODDropResult result)
  5137. {
  5138.     // If drag hiliting is on turn it off
  5139.     if (fHilightedDragFacet)
  5140.     {
  5141.         HiliteFacet(ev, this->GetSession(ev)->GetDragAndDrop(ev), fHilightedDragFacet, kODFalse);
  5142.         fHilightedDragFacet = kODNULL;
  5143.     }
  5144. }
  5145.  
  5146.  
  5147. //------------------------------------------------------------------------------
  5148. // Method:        DragEnter
  5149. // Origin:        ODPart
  5150. //
  5151. // Description:    Track the drag. The part should display a drag target border within 
  5152. //                 the facet. During drag tracking (DragEnter, DragWithin) the part should 
  5153. //                never attempt to read data from any of the storage units supplied
  5154. //                by the iterator. The part should only inspect the type of
  5155. //                the dragged data.
  5156. //
  5157. //                If the part can accept a drop, it should return 
  5158. //                kODTrue. Otherwise, it should return kODFalse.
  5159. //------------------------------------------------------------------------------
  5160.  
  5161. ODDragResult DrawEditor::DragEnter(Environment *ev, 
  5162.                                     ODDragItemIterator* dragInfo, 
  5163.                                     ODFacet* facet, 
  5164.                                     ODPoint*  where)
  5165. {
  5166.     // Do not accept drags if this draft is marked read only
  5167.     if (this->IsReadOnly())
  5168.         return kODFalse;
  5169.     
  5170.     // Do not accept drags if we are in low memory conditions
  5171.     TRY
  5172.         // Will throw if in low mem
  5173.         ::ODCheckAppHeapSpace();
  5174.     CATCH_ALL
  5175.         DebugStr("\pLo mem in drag enter.");
  5176.         return kODFalse;
  5177.     ENDTRY
  5178.     
  5179.     // We can accept anything
  5180.     
  5181.     // Highlight the facet if the drag has ( ever ) left the source frame.
  5182.     ODDragAndDrop* drag = this->GetSession(ev)->GetDragAndDrop(ev);
  5183.     ODULong        attributes = drag->GetDragAttributes(ev);
  5184.     ODBoolean     dragIsInSourceFrame = attributes & kODDragIsInSourceFrame;
  5185.     
  5186.     if (!dragIsInSourceFrame)
  5187.     {
  5188.         HiliteFacet(ev, GetSession(ev)->GetDragAndDrop(ev), facet, kODTrue);
  5189.         fHilightedDragFacet = facet;
  5190.     }
  5191.     
  5192.     return kODTrue;
  5193. }
  5194.  
  5195.  
  5196. //------------------------------------------------------------------------------
  5197. // Method:        DragLeave
  5198. // Origin:        ODPart
  5199. //
  5200. // Description:    This method is called by OpenDoc when a drag occurs within 
  5201. // a facet.
  5202. //------------------------------------------------------------------------------
  5203.  
  5204. void DrawEditor::DragLeave(Environment *ev, 
  5205.                                 ODFacet* facet, 
  5206.                                 ODPoint*  where)
  5207. {
  5208.     if (fHilightedDragFacet)
  5209.     {
  5210.         HiliteFacet(ev, GetSession(ev)->GetDragAndDrop(ev), facet, kODFalse);
  5211.         fHilightedDragFacet = kODNULL;
  5212.     }
  5213.  
  5214. }
  5215.  
  5216.  
  5217. //------------------------------------------------------------------------------
  5218. // Method:        DragWithin
  5219. // Origin:        ODPart
  5220. //
  5221. // Description:    This method is called by OpenDoc when a drag occurs within 
  5222. // a facet.
  5223. //------------------------------------------------------------------------------
  5224.  
  5225. ODDragResult DrawEditor::DragWithin(Environment *ev, 
  5226.                                     ODDragItemIterator* dragInfo, 
  5227.                                     ODFacet* facet, 
  5228.                                     ODPoint*  where)
  5229. {
  5230.     return kODTrue;
  5231. }
  5232.  
  5233.  
  5234. //------------------------------------------------------------------------------
  5235. // Method:        Drop
  5236. // Origin:        ODPart
  5237. //
  5238. // Description:    This method is called by OpenDoc when a drop occurs.
  5239. //------------------------------------------------------------------------------
  5240.  
  5241. ODDropResult DrawEditor::Drop(Environment *ev, 
  5242.                                 ODDragItemIterator* dragInfo, 
  5243.                                 ODFacet* facet, 
  5244.                                 ODPoint*  where)
  5245. {
  5246.     ODDropResult dropResult = kODDropFail;
  5247.  
  5248.     // ----- 'where' is in frame coordinate. Put it in content coordinate
  5249.     ODPoint dropPoint = *where;
  5250.     ODFrame* tFrame = facet->GetFrame(ev);
  5251.     ODTransform* frameTrans = tFrame->AcquireInternalTransform(ev, kODNULL);
  5252.     frameTrans->InvertPoint(ev, &dropPoint); // Drop point is modified in place
  5253.     ODReleaseObject(ev,frameTrans);
  5254.         
  5255.     // we need first to check the drag attributes and show a paste as dialog if so indicated
  5256.     // It would be nice to factor some common code from here and from DoPasteAs (for the menu choice)
  5257.     // but there are several little differences that make it a nuisance to do so.
  5258.     
  5259.     ODBoolean usePAResult = kODFalse;
  5260.     ODStorageUnit* dropSU = dragInfo->First(ev);
  5261.     ODBoolean canMerge = dropSU->Exists(ev, kODPropContents, kDrawEditorKind, 0);
  5262.     ODBoolean canEmbedSingleFrame = dropSU->Exists(ev, kODPropContentFrame, kODWeakStorageUnitRef, 0);
  5263.     ODPasteAsMergeSetting mergeSetting;
  5264.     ODPasteAsResult paResult;
  5265.     
  5266.     if (canMerge)
  5267.     {
  5268.         if (canEmbedSingleFrame)
  5269.             mergeSetting = kODPasteAsEmbed;
  5270.         else
  5271.             mergeSetting = kODPasteAsMerge;
  5272.     }
  5273.     else
  5274.         mergeSetting = kODPasteAsEmbedOnly;
  5275.  
  5276.     ODSession* session = this->GetSession(ev);
  5277.     ODDragAndDrop* drag = session->GetDragAndDrop(ev);
  5278.     ODULong attributes = drag->GetDragAttributes(ev);
  5279.         
  5280.     CDropShapeCommand* dropCommand = kODNULL;
  5281.     if (attributes & kODDropIsPasteAs)
  5282.     {
  5283.         
  5284.         usePAResult = drag->ShowPasteAsDialog(ev, kODTrue, mergeSetting, 
  5285.                                      facet,    // facet from which dialog is triggered
  5286.                                      session->Tokenize(ev, kODViewAsFrame), // viewType of data
  5287.                                      dropSU, &paResult);
  5288.         if (usePAResult)
  5289.         {
  5290.             TRY
  5291.                 ODBoolean doLink = paResult.pasteLinkSetting == kODTrue;
  5292.         
  5293.                 if (doLink)
  5294.                 {
  5295.                     ODBoolean defaultIsMerge = (mergeSetting == kODPasteAsMerge);
  5296.                     CDropLinkCommand* command = new CDropLinkCommand(this, fSelection, dropSU, dropPoint, paResult, defaultIsMerge);
  5297.                     this->ExecuteCommand(ev, command);
  5298.                     dropResult = kODDropCopy;
  5299.                 }
  5300.                 else
  5301.                 {
  5302.                     ODBoolean doMerge = canMerge && paResult.mergeSetting;
  5303.                 
  5304.                     // determine embed vs merge choice from paResult.
  5305.                     dropCommand = new CDropAsCommand(this, facet, dragInfo, fSelection, dropPoint, !doMerge);
  5306.                     this->ExecuteCommand(ev, dropCommand);
  5307.                     
  5308.                     // Remember the drop result
  5309.                     dropResult = dropCommand->GetDropResult();
  5310.                 }
  5311.                 
  5312.             CATCH_ALL
  5313.                 dropResult = kODDropFail;
  5314.             ENDTRY
  5315.         }
  5316.         else
  5317.         {
  5318.             // User cancelled.
  5319.             
  5320.             // Turn off drag highlight
  5321.             if (fHilightedDragFacet)
  5322.             {
  5323.                 HiliteFacet(ev, GetSession(ev)->GetDragAndDrop(ev), facet, kODFalse);
  5324.                 fHilightedDragFacet = kODNULL;
  5325.             }
  5326.             
  5327.             // Fail the drop
  5328.             dropResult = kODDropFail;  
  5329.         }
  5330.                                      
  5331.         // Dispose of pasteAsResult fields
  5332.         ODDisposePtr(paResult.selectedKind);
  5333.         ODDisposePtr(paResult.translateKind);
  5334.         ODDisposePtr(paResult.editor);
  5335.     }
  5336.     else
  5337.     {
  5338.             dropCommand = new CDropShapeCommand(this, facet, dragInfo, fSelection, dropPoint, kODTrue);
  5339.     
  5340.             // This should be safe to do since D&D is undoable, the command won't be deleted
  5341.             // right away. So, we can query the drop result in the next block.
  5342.             this->ExecuteCommand(ev, dropCommand);
  5343.             
  5344.             // Remember the drop result
  5345.             dropResult = dropCommand->GetDropResult();
  5346.     }
  5347.                     
  5348.     return dropResult;
  5349. }
  5350.  
  5351.  
  5352. //------------------------------------------------------------------------------
  5353. // Method:        HandleMouseDownInEmbeddedFrame
  5354. // Origin:        DrawEditor
  5355. //
  5356. // Description:    This method is called by the part to handle mouse down
  5357. //                events that occur in embedded frames.
  5358. //
  5359. //------------------------------------------------------------------------------
  5360.  
  5361. ODBoolean DrawEditor::HandleMouseDownInEmbeddedFrame( Environment*    ev,
  5362.                                                 ODFacet*        facet,
  5363.                                                 ODEventData*    event,
  5364.                                                 ODEventInfo*    eventInfo )
  5365. {
  5366.     
  5367.     //  Check the embedded frame parameter
  5368.     ODFrame* embeddedFrame = eventInfo->embeddedFrame;
  5369.     if (embeddedFrame==kODNULL)
  5370.         return kODFalse;
  5371.     
  5372.     // Get the shape for the frame clicked on, check that it's valid
  5373.     CShape* tShape = this->ShapeForFrame(ev, eventInfo->embeddedFrame);
  5374.     if (tShape==kODNULL)
  5375.         return kODFalse;
  5376.     
  5377.     fSelection->SelectWithShape(ev, facet, event, tShape);
  5378.     return kODTrue;
  5379. }
  5380.  
  5381.  
  5382. //------------------------------------------------------------------------------
  5383. // Method:        HandleMouseDownInEmbeddedFrameBorder
  5384. // Origin:        DrawEditor
  5385. //
  5386. // Description:    This method is called by the part to handle mouse down
  5387. //                events that occur in embedded frame borders.
  5388. //
  5389. //------------------------------------------------------------------------------
  5390.  
  5391. ODBoolean DrawEditor::HandleMouseDownInEmbeddedFrameBorder( Environment*    ev,
  5392.                                                         ODFacet*        facet,
  5393.                                                         ODEventData*    event,
  5394.                                                         ODEventInfo*    eventInfo )
  5395. {
  5396.     //  Check the embedded frame parameter
  5397.     ODFrame* embeddedFrame = eventInfo->embeddedFrame;
  5398.     if (embeddedFrame==kODNULL)
  5399.         return kODFalse;
  5400.     
  5401.     // Get the shape for the frame clicked on, check that its valid
  5402.     CShape* tShape = this->ShapeForFrame(ev, eventInfo->embeddedFrame);
  5403.     if (tShape==kODNULL)
  5404.         return kODFalse;
  5405.     
  5406.     fSelection->SelectWithShape(ev, facet, event, tShape);
  5407.     
  5408.     return kODTrue;
  5409. }
  5410.  
  5411.  
  5412. //------------------------------------------------------------------------------
  5413. // Method:        HandleMouseDown
  5414. // Origin:        DrawEditor
  5415. //
  5416. // Description:    This method is called by the part to handle mouse
  5417. //                events.
  5418. //------------------------------------------------------------------------------
  5419.  
  5420. void DrawEditor::HandleMouseDown( Environment*    ev,
  5421.                                 ODFacet*        facet,
  5422.                                 ODEventData*    event,
  5423.                                 ODEventInfo*    eventInfo )
  5424. {
  5425.     SOM_Trace("DrawEditor","HandleMouseDown");
  5426.     
  5427.     // Get the window
  5428.     ODWindow* window = facet->GetWindow(ev);
  5429.  
  5430.     // Get the localized mouse coordinates from the Event Info.
  5431.     Point where;
  5432.     where.h = FixedToInt(eventInfo->where.x);
  5433.     where.v = FixedToInt(eventInfo->where.y);
  5434.     
  5435.     // Don't handle mouse downs in inactive windows, unless the mousedown is in
  5436.     // a shape.
  5437.     CShape* shape = this->WhichShape(ev, where);
  5438.  
  5439.     if ( !window->IsActive(ev)&&!shape)
  5440.     {
  5441.         window->Select(ev);
  5442.         return;
  5443.     }
  5444.     
  5445.  
  5446.     // HandleMouseDowns in Palettes
  5447.     ODTypeToken presentation = facet->GetFrame(ev)->GetPresentation(ev);
  5448.     if (presentation == gGlobals->fColorPalette->GetPresentation())
  5449.     {
  5450.         ODSShort paletteItem;
  5451.         ODBoolean selectionIsEmpty = fSelection->IsEmpty();
  5452.         if(gGlobals->fColorPalette->DoMouseDownInPalette(ev, facet->GetFrame(ev), 
  5453.                                     where, &paletteItem, selectionIsEmpty))
  5454.         {
  5455.             if (!this->IsReadOnly())
  5456.             {
  5457.                 
  5458.                 //  Can't change color of link destination content.
  5459.                 CSubscribeLink* link = kODNULL;
  5460.                 if (fLinkStatus == kODInLinkDestination || !fSelection->CanEditSelectedContent(link))
  5461.                     this->EditInLink(ev, link);
  5462.                 
  5463.                 // if the user chose to break the link, then the status may have changed
  5464.                 // so check again.
  5465.                 
  5466.                 if (fLinkStatus != kODInLinkDestination && fSelection->CanEditSelectedContent())
  5467.                 {
  5468.                     CRGBColor color;
  5469.                     gGlobals->fColorPalette->GetColor(paletteItem, &color);
  5470.                     
  5471.                     CColorSelectionCommand* command = 
  5472.                         new CColorSelectionCommand(this, fSelection, color);
  5473.                         
  5474.                     this->ExecuteCommand(ev, command);
  5475.                 }
  5476.             }
  5477.         }
  5478.     }
  5479.     else
  5480.     if (presentation == gGlobals->fToolPalette->GetPresentation())
  5481.         gGlobals->fToolPalette->DoMouseDownInPalette(ev, facet->GetFrame(ev), where);
  5482.     else
  5483.     if (presentation == gGlobals->fMainPresentation)
  5484.     {
  5485.         // Get the current tool
  5486.         ODSShort currentTool = gGlobals->fToolPalette->GetSelectedPaletteItem();
  5487.         
  5488.         switch (currentTool) 
  5489.         {
  5490.             case kSelectionTool:
  5491.                 // Try to select something
  5492.                 this->HandleSelection(ev, facet, event, eventInfo);
  5493.                 break;
  5494.         
  5495.             case kLineShapeTool:
  5496.                 //  Create a line shape.
  5497.                 break;
  5498.         
  5499.             case kOvalTool:
  5500.             case kPolygonTool:
  5501.             case kRectangleTool:
  5502.             case kTextTool:
  5503.             
  5504.                 CFocus draw(ev, facet);
  5505.                 
  5506.                 // Get rectangle
  5507.                 Rect shapeRect;
  5508.                 CRGBColor shapeColor;
  5509.                 gGlobals->fColorPalette->GetColor(gGlobals->fColorPalette->GetSelectedPaletteItem(), &shapeColor);
  5510.                 
  5511.                 fSelection->TrackRectangle(ev, event, &shapeRect);
  5512.                 
  5513.                 // Do not create a shape if the rectangle is too small or invalid
  5514.                 if (::RectContainsRect(shapeRect, gGlobals->fMinShapeSizeRect) || !::IsValidRect(shapeRect))
  5515.                 {
  5516.                     fSelection->CloseSelection(ev);
  5517.                     return;
  5518.                 }
  5519.                 
  5520.                 // Create the new shape command and execute it.
  5521.                 CNewShapeCommand* command = new CNewShapeCommand(this, facet, shapeRect, shapeColor, 
  5522.                                                     currentTool,fSelection);
  5523.                 this->ExecuteCommand(ev, command);
  5524.                 break;
  5525.         }
  5526.     }
  5527. }
  5528.  
  5529.  
  5530. //------------------------------------------------------------------------------
  5531. // Method:        DoOpen
  5532. // Origin:        DrawEditor
  5533. //
  5534. // Description:    Open all selected embedded parts into windows.
  5535. //------------------------------------------------------------------------------
  5536.  
  5537. void DrawEditor::DoOpen(Environment* ev, ODFrame* frame)
  5538. {
  5539.     COrdListIterator iter(fSelection->GetShapeList());
  5540.  
  5541.     for ( CShape* shape = (CShape*)iter.First();
  5542.          iter.IsNotComplete();
  5543.          shape = (CShape*)iter.Next() )
  5544.     {
  5545.         shape->Open(ev, frame);
  5546.     }
  5547.  
  5548. }
  5549.  
  5550.  
  5551. //------------------------------------------------------------------------------
  5552. // Method:        DoClear
  5553. // Origin:        DrawEditor
  5554. //
  5555. // Description:    This method is called by HandleMenuEvent to clear the current
  5556. // selection.
  5557. //------------------------------------------------------------------------------
  5558.  
  5559. ODBoolean DrawEditor::DoClear(Environment* ev, ODFrame* frame)
  5560. {
  5561.     CCutCopyClearShapeCommand* command = new CCutCopyClearShapeCommand(this, 
  5562.                                                     frame, fSelection,
  5563.                                                     kODCommandClear);
  5564.     
  5565.     this->ExecuteCommand(ev, command);
  5566.     return kODTrue;
  5567. }
  5568.  
  5569.  
  5570. //------------------------------------------------------------------------------
  5571. // Method:        DoPasteAs
  5572. // Origin:        DrawEditor
  5573. //
  5574. // Description:    This method is called by HandleMenuEvent to paste the contents 
  5575. // of the clipboard to the document. Embed Vs. Incorporate and Linking are dealt
  5576. // with here as well.
  5577. //------------------------------------------------------------------------------
  5578.  
  5579. ODBoolean DrawEditor::DoPasteAs(Environment* ev, ODFrame* frame, ODFacet* facet)
  5580. {
  5581.     // Get the clipboard storage unit and internalize it
  5582.     ODClipboard* clip = this->GetSession(ev)->GetClipboard(ev);
  5583.     
  5584.     // Get the clipboard content storage unit
  5585.     ODStorageUnit* contentSU = clip->GetContentStorageUnit(ev);
  5586.     
  5587.     ASSERT_NOT_NULL(contentSU->Exists(ev, kODPropContents, kODNULL, 0));
  5588.  
  5589.     ODBoolean result;
  5590.     ODBoolean canMerge = contentSU->Exists(ev, kODPropContents, kDrawEditorKind, 0);
  5591.     ODBoolean canEmbedSingleFrame = contentSU->Exists(ev, kODPropContentFrame, kODWeakStorageUnitRef, 0);
  5592.     ODPasteAsMergeSetting mergeSetting;
  5593.     ODPasteAsResult paResult;
  5594.     
  5595.     if (canMerge)
  5596.     {
  5597.         if (canEmbedSingleFrame)
  5598.             mergeSetting = kODPasteAsEmbed;
  5599.         else
  5600.             mergeSetting = kODPasteAsMerge;
  5601.     }
  5602.     else
  5603.         mergeSetting = kODPasteAsEmbedOnly;
  5604.             
  5605.     // ---- Display the Paste As... dialog ----
  5606.     result = clip->ShowPasteAsDialog(ev, kODTrue, mergeSetting, 
  5607.                                      facet,    // facet from which dialog is triggered
  5608.                                      gGlobals->fFrameView, // viewType of data
  5609.                                       &paResult);
  5610.     if (result)
  5611.     {
  5612.         TRY
  5613.             ODBoolean doLink = paResult.pasteLinkSetting == kODTrue;
  5614.     
  5615.             if (doLink)
  5616.             {
  5617.                 ODBoolean defaultIsMerge = (mergeSetting == kODPasteAsMerge);
  5618.                 CPasteLinkCommand* command = new CPasteLinkCommand(this, fSelection, contentSU, paResult, defaultIsMerge);
  5619.                 this->ExecuteCommand(ev, command);
  5620.             }
  5621.             else
  5622.             {
  5623.                 // Since this part only supports 1 kind, we can ignore that translation
  5624.                 // result portion of paResult. The paste as command will do the right
  5625.                 // thing in the native kind case. We need to worry about the force
  5626.                 // embed case.
  5627.                 CPasteAsCommand* command = new CPasteAsCommand(this, frame, fSelection, !paResult.mergeSetting);
  5628.                 this->ExecuteCommand(ev, command);
  5629.             }
  5630.         CATCH_ALL
  5631.             // ExecuteCommand sahould clean up command
  5632.             
  5633.             // Dispose of pasteAsResult fields
  5634.             ODDisposePtr(paResult.selectedKind);
  5635.             ODDisposePtr(paResult.translateKind);
  5636.             ODDisposePtr(paResult.editor);
  5637.             
  5638.             RERAISE;
  5639.         ENDTRY
  5640.     }
  5641.     
  5642.     // Dispose of pasteAsResult fields
  5643.     ODDisposePtr(paResult.selectedKind);
  5644.     ODDisposePtr(paResult.translateKind);
  5645.     ODDisposePtr(paResult.editor);
  5646.         
  5647.     
  5648.     return kODTrue;
  5649. }
  5650.  
  5651.  
  5652. //------------------------------------------------------------------------------
  5653. // Method:        DoPaste
  5654. // Origin:        DrawEditor
  5655. //
  5656. // Description:    This method is called by HandleMenuEvent to paste the contents 
  5657. // of the clipboard to the document.
  5658. //------------------------------------------------------------------------------
  5659.  
  5660. ODBoolean DrawEditor::DoPaste(Environment* ev, ODFrame* frame)
  5661. {
  5662.     CPasteCommand* command = new CPasteCommand(this, frame, fSelection);
  5663.     this->ExecuteCommand(ev, command);
  5664.     
  5665.     return kODTrue;
  5666. }
  5667.  
  5668.  
  5669. //------------------------------------------------------------------------------
  5670. // Method:        DoCutCopy
  5671. // Origin:        DrawEditor
  5672. //
  5673. // Description:    This method is called by HandleMenuEvent to cut/copy the current 
  5674. // selection to the clipboard.
  5675. //------------------------------------------------------------------------------
  5676.  
  5677. ODBoolean DrawEditor::DoCutCopy(Environment* ev, 
  5678.                                 ODCommandID commandID, 
  5679.                                 ODFrame* frame)
  5680. {
  5681.     CCutCopyClearShapeCommand* command = new CCutCopyClearShapeCommand(this, 
  5682.                                                             frame, 
  5683.                                                             fSelection, 
  5684.                                                             commandID);
  5685.     this->ExecuteCommand(ev, command);
  5686.     return kODTrue;
  5687. }
  5688.  
  5689.  
  5690. //------------------------------------------------------------------------------
  5691. // Method:        EmbeddedFrameUpdated
  5692. // Origin:        ODPart
  5693. //
  5694. // Description:    This method makes OpenDoc calls necessary before a dialog is 
  5695. // displayed. This method returns false if it can't successfully prepare 
  5696. // ( i.e can't get modal focus ).
  5697. //------------------------------------------------------------------------------
  5698.  
  5699. void DrawEditor::EmbeddedFrameUpdated( Environment* ev, 
  5700.                                             ODFrame* frame, ODUpdateID updateID )
  5701. {
  5702.     CShape* shape = this->ShapeForFrame(ev, frame);
  5703.     
  5704.     ASSERT_NOT_NULL(shape);
  5705.     
  5706.     COrdListIterator iter(shape->GetPublishLinks());
  5707.     for (CPublishLink* link = (CPublishLink*)iter.First(); iter.IsNotComplete(); link = (CPublishLink*)iter.Next())
  5708.     {
  5709.         link->ContentUpdated(ev, updateID);
  5710.     }
  5711.     
  5712.     return;
  5713. }
  5714.  
  5715.  
  5716. //------------------------------------------------------------------------------
  5717. // Method:        PrepareForDialog
  5718. // Origin:        DrawEditor
  5719. //
  5720. // Description:    This method makes OpenDoc calls necessary before a dialog is displayed.
  5721. // This method returns false if it can't successfully prepare ( i.e can't get modal focus ).
  5722. //------------------------------------------------------------------------------
  5723.  
  5724. ODBoolean DrawEditor::PrepareForDialog( Environment* ev, ODFrame* frame )
  5725. {
  5726.     SOM_Trace("DrawEditor","PrepareForDialog");
  5727.  
  5728.     ODSession*    session = GetODPart()->GetStorageUnit(ev)->GetSession(ev);
  5729.     
  5730.     // Our About box is modal so we must request the Modal focus to prevent
  5731.     // multiple modal dialogs being displayed simultaneously.
  5732.     
  5733.     if ( session->GetArbitrator(ev)->RequestFocus(ev, gGlobals->fModalFocus, frame) )
  5734.     {
  5735.         TRY
  5736.             // Dim the frontmost document window.
  5737.             session->GetWindowState(ev)->DeactivateFrontWindows(ev);
  5738.             return kODTrue;
  5739.         CATCH_ALL
  5740.             session->GetArbitrator(ev)->RelinquishFocus(ev, gGlobals->fModalFocus, frame);
  5741.             RERAISE;
  5742.         ENDTRY
  5743.     }
  5744.     
  5745.     return kODFalse;
  5746. }
  5747.  
  5748. //------------------------------------------------------------------------------
  5749. // Method:        DoneWithDialog
  5750. // Origin:        DrawEditor
  5751. //
  5752. // Description:    This method makes OpenDoc calls necessary when a dialog is closed.
  5753. //------------------------------------------------------------------------------
  5754.  
  5755. void DrawEditor::DoneWithDialog( Environment* ev, ODFrame* frame )
  5756. {
  5757.     SOM_Trace("DrawEditor","DoneWithDialog");
  5758.  
  5759.     ODSession*    session = GetODPart()->GetStorageUnit(ev)->GetSession(ev);
  5760.     
  5761.     // Inform the Arbitrator that we no longer require the Modal focus.
  5762.     session->GetArbitrator(ev)->RelinquishFocus(ev, gGlobals->fModalFocus, frame);
  5763.     
  5764.     // Hilite the frontmost document window.
  5765.     session->GetWindowState(ev)->ActivateFrontWindows(ev);
  5766. }
  5767.  
  5768. //------------------------------------------------------------------------------
  5769. // Method:        DoDialogBox
  5770. // Origin:        DrawEditor
  5771. //
  5772. // Description:    This method is called by the part when a dialog needs to be
  5773. //                displayed (ie. the About Box). If a valid error number is passed
  5774. //                in, an error dialog will be displayed.
  5775. //------------------------------------------------------------------------------
  5776.  
  5777. void DrawEditor::DoDialogBox( Environment*    ev,
  5778.                               ODFrame*        frame,
  5779.                               ODSShort        dialogID,
  5780.                               ODUShort        errorNumber )
  5781. {
  5782.     SOM_Trace("DrawEditor","DoDialogBox");
  5783.  
  5784.     ODFrame* focusFrame = frame;
  5785.     ODSession*    session = ODGetSession(ev,fSelf);
  5786.     
  5787.     // If the calling method does not have a frame available to it, we need to
  5788.     // locate a frame to use for requesting the modal focus. Find the first valid
  5789.     // frame in our display frames list.
  5790.     if ( focusFrame == kODNULL )
  5791.     {
  5792.         COrdListIterator fiter(fDisplayFrameProxies);
  5793.         for ( CDisplayFrameProxy* frameProxy = (CDisplayFrameProxy*)fiter.First();
  5794.                 fiter.IsNotComplete();
  5795.                 frameProxy = (CDisplayFrameProxy*)fiter.Next())
  5796.         {
  5797.             // shouldn't get called to remove a frame that has
  5798.             // not yet been internalized
  5799.             if (frameProxy->IsFrameInMemory())
  5800.             {
  5801.                 if (frameProxy->GetFrame(ev))
  5802.                 {
  5803.                     focusFrame = frameProxy->GetFrame(ev); 
  5804.                 }
  5805.             }
  5806.         }
  5807.     }
  5808.     
  5809.     // Our dialog boxes are modal so we must request the Modal focus to prevent
  5810.     // multiple modal dialogs being displayed simultaneously.
  5811.     
  5812.     if ( this->PrepareForDialog(ev, frame) )
  5813.     {
  5814.         DialogPtr    dialog;
  5815.         ODSShort    itemHit;
  5816.  
  5817.         ODSLong rfRef;
  5818.         rfRef = BeginUsingLibraryResources();
  5819.         {            
  5820.             dialog = GetNewDialog(dialogID, kODNULL, (WindowPtr) -1L);
  5821.             
  5822.             if ( dialog )
  5823.             {
  5824.                 if ( errorNumber > 0 )
  5825.                 {
  5826.                     Handle    itemHandle;
  5827.                     Rect    itemRect;
  5828.                     short    itemType;
  5829.                     Str255    errStr;
  5830.                     
  5831.                     GetIndString(errStr, kErrorStringResID, errorNumber);
  5832.                     GetDialogItem(dialog, kErrStrFieldID, &itemType, &itemHandle, &itemRect);
  5833.                     SetDialogItemText(itemHandle, errStr);
  5834.                     
  5835.                     // We don't need the cancel button for an error dialog.
  5836.                     HideDialogItem(dialog, cancel);
  5837.  
  5838.                     SetDialogDefaultItem(dialog, ok);
  5839.                 }
  5840.                 
  5841.                 SetCursor(&ODQDGlobals.arrow);
  5842.                 ShowWindow(dialog);
  5843.                 ModalDialog(kODNULL, &itemHit);
  5844.                 DisposeDialog(dialog);
  5845.             }
  5846.             else
  5847.             {
  5848.                 // Could not load About box dialog... something is amiss.
  5849.                 SysBeep(2);
  5850.             }
  5851.         }
  5852.         EndUsingLibraryResources(rfRef);
  5853.         
  5854.         this->DoneWithDialog(ev, frame);
  5855.     }
  5856.     else
  5857.         // If we can't get the modal focus, then another modal dialog is
  5858.         // already being displayed.
  5859.         SysBeep(2);
  5860. }
  5861.  
  5862.  
  5863.  
  5864. //------------------------------------------------------------------------------
  5865. // Method:        MoveShapeBefore
  5866. // Origin:        DrawEditor
  5867. //
  5868. // Description:    This method moves the given shape before the 'before' shape
  5869. // in our content shape list. It then calls the shape method MoveBefore.
  5870. //------------------------------------------------------------------------------
  5871. void DrawEditor::MoveShapeBefore(Environment* ev, CShape* moveShape, CShape* before)
  5872. {
  5873.     // Don't try to remove if either shape is null
  5874.     if (moveShape==kODNULL || before==kODNULL)
  5875.         return;
  5876.         
  5877.     // Also, don't try to do anything if the shapes are the same
  5878.     if (before==moveShape)
  5879.         return;
  5880.     
  5881.     fShapeList->Remove(moveShape);
  5882.     fShapeList->AddBefore(before, moveShape);
  5883.     
  5884.     moveShape->MoveBefore(ev, before);
  5885. }
  5886.  
  5887.  
  5888. //------------------------------------------------------------------------------
  5889. // Method:        MoveShapeAfter
  5890. // Origin:        DrawEditor
  5891. //
  5892. // Description:    This method moves the given shape after the 'after' shape
  5893. // in our content shape list. It then calls the shape method MovedAfter.
  5894. //------------------------------------------------------------------------------
  5895. void DrawEditor::MoveShapeAfter(Environment* ev, CShape* moveShape, CShape* after)
  5896. {
  5897.     // Don't try to remove if either shape is null
  5898.     if (moveShape==kODNULL || after==kODNULL)
  5899.         return;
  5900.         
  5901.     // Also, don't try to do anything if the shapes are the same
  5902.     if (after==moveShape)
  5903.         return;
  5904.     
  5905.     fShapeList->Remove(moveShape);
  5906.     fShapeList->AddAfter(after, moveShape);
  5907.     
  5908.     moveShape->MoveAfter(ev, after);
  5909. }
  5910.  
  5911.  
  5912. //------------------------------------------------------------------------------
  5913. // Method:        ShapeForFrame
  5914. // Origin:        DrawEditor
  5915. //
  5916. // Description:    This method should return the embedding shape that is representing
  5917. // the given embedded frame.
  5918. //
  5919. // This method should be used primarily for event handlers which get passed 
  5920. // that the user is manipulating.
  5921. //------------------------------------------------------------------------------
  5922.  
  5923. CShape* DrawEditor::ShapeForFrame(Environment* ev, ODFrame* embeddedFrame)
  5924. {
  5925.     COrdListIterator iter(fShapeList);
  5926.     for (CShape* shape = (CShape*)iter.First(); iter.IsNotComplete(); shape = (CShape*)iter.Next())
  5927.     {
  5928.         ODBoolean itsThere = shape->ContainsProxyForFrame(ev, embeddedFrame);
  5929.         if (itsThere)
  5930.             return shape;
  5931.     }
  5932.     
  5933.     return kODNULL;
  5934. }
  5935.  
  5936. //------------------------------------------------------------------------------
  5937. // Method:        InvalidateShape
  5938. // Origin:        DrawEditor
  5939. //
  5940. // Description:    This method causes the given Shapes area to be redrawn.
  5941. //------------------------------------------------------------------------------
  5942.  
  5943. void DrawEditor::InvalidateShape(Environment* ev, CShape* shape)
  5944. {
  5945.     TRY
  5946.         COrderedList* contentFrames = this->GetContentDisplayFrames(ev);
  5947.         if (contentFrames)
  5948.         {
  5949.                 
  5950.             // If we have any display frames..
  5951.             if (contentFrames->Count()>0)
  5952.             {
  5953.                 // Then iterate over our them
  5954.                 COrdListIterator iter(contentFrames);
  5955.                 
  5956.                 // Create a tempory shape to use to invalidate the CShape
  5957.                 ODShape* tShape = ((ODFrame*)iter.First())->CreateShape(ev);
  5958.                 shape->GetUpdateShape(ev, tShape);
  5959.                 
  5960.                 // invalidate the shapes area in all of our content frames
  5961.                 for ( ODFrame* frame = (ODFrame*)iter.First();
  5962.                      iter.IsNotComplete();
  5963.                      frame = (ODFrame*)iter.Next() )
  5964.                 {
  5965.                     frame->Invalidate(ev, tShape, kODNULL);
  5966.                 }
  5967.             
  5968.                 // Release acquired geometry
  5969.                 ODReleaseObject(ev,tShape);
  5970.             }
  5971.         }
  5972.         
  5973.         
  5974.         // Delete temp list
  5975.         delete contentFrames;
  5976.     CATCH_ALL
  5977.     ENDTRY
  5978. }
  5979.  
  5980. //------------------------------------------------------------------------------
  5981. // Method:        AddShape
  5982. // Origin:        DrawEditor
  5983. //
  5984. // Description:    This method adds the given shape to our list.
  5985. //------------------------------------------------------------------------------
  5986.  
  5987. void DrawEditor::AddShape(Environment* ev, CShape* shape)
  5988. {
  5989.     fShapeList->AddFirst(shape);
  5990.     
  5991.     // If shape is visible, invalidate
  5992.     this->InvalidateShape(ev, shape);
  5993.     
  5994.     shape->Added(ev);
  5995. }
  5996.  
  5997. //------------------------------------------------------------------------------
  5998. // Method:        RemoveShape
  5999. // Origin:        DrawEditor
  6000. //
  6001. // Description:    This method removes the given shape from our list and temporarily
  6002. // removes it from the document ( if it is an embedded shape ).
  6003. //------------------------------------------------------------------------------
  6004.  
  6005. void DrawEditor::RemoveShape(Environment* ev, CShape* shape)
  6006. {
  6007.     fShapeList->Remove(shape);
  6008.     this->InvalidateShape(ev, shape);
  6009.     shape->Removed(ev, kDontCommit);
  6010. }
  6011.  
  6012.  
  6013. //-----------------------------------------------------------------------------
  6014. // DrawEditor::WhichShape
  6015. // Origin:        DrawEditor
  6016. //-----------------------------------------------------------------------------
  6017.  
  6018. CShape* DrawEditor::WhichShape(Environment *ev, Point& where)
  6019. {
  6020.     COrdListIterator iter(fShapeList);
  6021.     for (CShape* shape = (CShape*)iter.First(); iter.IsNotComplete(); shape = (CShape*)iter.Next())
  6022.     {
  6023.         if (shape->HitTest(ev, where))
  6024.             return shape;    
  6025.     }
  6026.     
  6027.     return kODNULL;
  6028. }
  6029.  
  6030.  
  6031. //------------------------------------------------------------------------------
  6032. // Method:        CreateShape
  6033. // Origin:        DrawEditor
  6034. //
  6035. // Description:    This method creates the enumerated shape and returns a pointer to it.
  6036. //------------------------------------------------------------------------------
  6037.  
  6038. CShape* DrawEditor::CreateShape(Environment* ev, ODSShort shapeType, Rect shapeBounds)
  6039. {
  6040.     SOM_Trace("DrawEditor","CreateShape");
  6041.     
  6042.     CShape* theShape = kODNULL;
  6043.     
  6044.     switch (shapeType) 
  6045.     {
  6046.         case kRectShape:
  6047.             {
  6048.                 theShape = new CRectangleShape();
  6049.                 break;
  6050.             }
  6051.         case kOvalShape:
  6052.             {
  6053.                 theShape = new COvalShape();
  6054.                 break;
  6055.             }
  6056.             
  6057.         case kEmbeddingShape:
  6058.             {
  6059.                 theShape = new CEmbeddingShape(this);
  6060.                 break;
  6061.             }
  6062.         case kPolygonShape:
  6063.             {
  6064.                 theShape = new CPolygonShape();
  6065.                 ((CPolygonShape*)theShape)->SetPolygon(3);
  6066.                 break;
  6067.             }
  6068.         /*
  6069.         case kLineShape:
  6070.             theShape = new CLineShape();
  6071.             break;
  6072.         */
  6073.     }
  6074.     
  6075.     // Set the bounding box
  6076.     if (theShape)
  6077.         theShape->SetBoundingBox(ev, shapeBounds);
  6078.     
  6079.     // return the shape
  6080.     return theShape;
  6081. }
  6082.  
  6083. //------------------------------------------------------------------------------
  6084. // Method:        SetPendingPublish
  6085. // Origin:        DrawEditor
  6086. //
  6087. // Description:    
  6088. //------------------------------------------------------------------------------
  6089. void DrawEditor::SetPendingPublish(CPublishLink *link)
  6090. {
  6091.     // This is only called after clearing the clipboard, so rather than call DeletePendingPublish
  6092.     // we can avoid the overhead of checking the clipboard that we've just cleared
  6093.     
  6094.     if (fPendingPublish && fPendingPublish->CanDelete())
  6095.     {
  6096.         // The setters for the two pending publish members should insure that they never
  6097.         // contain the same non-null reference
  6098.         
  6099.         ASSERT(fPendingPublish != fPendingDragPublish, kODErrAssertionFailed);
  6100.         delete fPendingPublish;
  6101.     }
  6102.     
  6103.     // fPendingDragPublish is only used when we have two different pending publishers
  6104.     
  6105.     if (fPendingDragPublish == link)
  6106.         fPendingDragPublish = kODNULL;
  6107.  
  6108.     fPendingPublish = link;
  6109.     
  6110. }
  6111.  
  6112.  
  6113. //------------------------------------------------------------------------------
  6114. // Method:        SetPendingDragPublish
  6115. // Origin:        DrawEditor
  6116. //
  6117. // Description:    
  6118. //------------------------------------------------------------------------------
  6119. void DrawEditor::SetPendingDragPublish(CPublishLink *link)
  6120. {
  6121.         
  6122.     if (fPendingDragPublish)
  6123.         if (fPendingDragPublish->CanDelete())     
  6124.             delete fPendingDragPublish;
  6125.             
  6126.     // PendingDragPublish is only used when we need to have two distinct 
  6127.     // publishers pending.  If this is the same one as is already pending for the 
  6128.     // clipboard, then just clear the previous reference in fPendingDragPublish
  6129.     
  6130.     if (link == fPendingPublish)
  6131.         fPendingDragPublish = NULL;
  6132.     else
  6133.         fPendingDragPublish = link;
  6134. }
  6135.  
  6136.  
  6137. //------------------------------------------------------------------------------
  6138. // Method:        DeletePendingPublish
  6139. // Origin:        DrawEditor
  6140. //
  6141. // Description:    
  6142. //------------------------------------------------------------------------------
  6143. void DrawEditor::DeletePendingPublish(Environment* ev)
  6144. {
  6145.     if (fPendingPublish != NULL)
  6146.     {
  6147.         ODClipboard* clipboard = GetSession(ev)->GetClipboard(ev);
  6148.         
  6149.         if (fPendingPublish->GetPendingID() == clipboard->GetUpdateID(ev)) 
  6150.         {
  6151.             ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
  6152.             if (clipboardSU->Exists(ev, kODPropLinkSpec, (ODValueType) NULL, 0) == TRUE) 
  6153.             {
  6154.                 clipboardSU->Focus(ev, kODPropLinkSpec, kODPosUndefined, (ODValueType) NULL, 0, kODPosUndefined);
  6155.                 clipboardSU->Remove(ev);
  6156.             }
  6157.         }
  6158.         
  6159.         if (fPendingPublish->CanDelete() && fPendingPublish != fPendingDragPublish)
  6160.             delete fPendingPublish;
  6161.  
  6162.         fPendingPublish = NULL;
  6163.     }
  6164. }
  6165.  
  6166.  
  6167. //------------------------------------------------------------------------------
  6168. // Method:        AddPublishLink
  6169. // Origin:        DrawEditor
  6170. //
  6171. // Description:    
  6172. //------------------------------------------------------------------------------
  6173. void DrawEditor::AddPublishLink(CPublishLink *link)
  6174. {
  6175.     fPublishLinks->AddLast(link);
  6176. }
  6177.  
  6178.  
  6179. //------------------------------------------------------------------------------
  6180. // Method:        RemovePublishLink
  6181. // Origin:        DrawEditor
  6182. //
  6183. // Description:    
  6184. //------------------------------------------------------------------------------
  6185. void DrawEditor::RemovePublishLink(Environment* ev, CPublishLink *link)
  6186. {
  6187.     fPublishLinks->Remove(link);
  6188.  
  6189.     if (link == fPendingPublish)
  6190.         this->DeletePendingPublish(ev);
  6191. }
  6192.  
  6193.  
  6194. //------------------------------------------------------------------------------
  6195. // Method:        CreateLink
  6196. // Origin:        ODPart
  6197. //
  6198. // Description:    
  6199. //------------------------------------------------------------------------------
  6200. ODLinkSource*    DrawEditor::CreateLink(Environment *ev, ODByteArray* data)
  6201. {
  6202.     ODLinkSource* odLinkSource = kODNULL;
  6203.  
  6204.     LinkSpecData lsData = *((LinkSpecData*)(data->_buffer));
  6205.     ODUpdateID updateID = lsData.fUpdateID;
  6206.     CDragShapeCommand* dragCommand = lsData.fCommand;
  6207.     
  6208.     CPublishLink* pendingPublish = kODNULL;
  6209.     
  6210.     if (fPendingDragPublish && (fPendingDragPublish->GetPendingID() == updateID)) 
  6211.         pendingPublish = fPendingDragPublish;
  6212.     else if (fPendingPublish && (fPendingPublish->GetPendingID() == updateID))
  6213.         pendingPublish = fPendingPublish;
  6214.     
  6215.     // -- Make sure we got one.
  6216.     ASSERT_NOT_NULL(pendingPublish);
  6217.  
  6218.     if (!pendingPublish->IsPublished())    
  6219.     {
  6220.         if (dragCommand)
  6221.         {
  6222.             dragCommand->CreateLink(ev, pendingPublish);
  6223.         }
  6224.         else
  6225.         {
  6226.             CCreateLinkCommand* command = new CCreateLinkCommand(this, pendingPublish);
  6227.             this->ExecuteCommand(ev, command);
  6228.         }
  6229.     }
  6230.     else
  6231.     {
  6232.         pendingPublish->ContentUpdated(ev, kODUnknownUpdate, kODTrue);
  6233.     }
  6234.     
  6235.     odLinkSource = pendingPublish->GetODLinkSource();
  6236.     odLinkSource->Acquire(ev);
  6237.     return odLinkSource;
  6238. }
  6239.  
  6240. //------------------------------------------------------------------------------
  6241. // Method:        AddSubscribeLink
  6242. // Origin:        DrawEditor
  6243. //
  6244. // Description:    
  6245. //------------------------------------------------------------------------------
  6246. void DrawEditor::AddSubscribeLink(CSubscribeLink* link)
  6247. {
  6248.     fSubscribeLinks->AddLast(link);
  6249. }
  6250.  
  6251. //------------------------------------------------------------------------------
  6252. // Method:        RemoveSubscribeLink
  6253. // Origin:        DrawEditor
  6254. //
  6255. // Description:    
  6256. //------------------------------------------------------------------------------
  6257. void DrawEditor::RemoveSubscribeLink(CSubscribeLink* link)
  6258. {
  6259.     fSubscribeLinks->Remove(link);
  6260. }
  6261.  
  6262.  
  6263. //------------------------------------------------------------------------------
  6264. // Method:        GetSubscribeLinks
  6265. // Origin:        DrawEditor
  6266. //
  6267. // Description:    
  6268. //------------------------------------------------------------------------------
  6269. COrderedList* DrawEditor::GetSubscribeLinks()
  6270. {
  6271.     return fSubscribeLinks;
  6272. }
  6273.  
  6274.  
  6275. //------------------------------------------------------------------------------
  6276. // Method:        GetPublishLinks
  6277. // Origin:        DrawEditor
  6278. //
  6279. // Description:    
  6280. //------------------------------------------------------------------------------
  6281. COrderedList* DrawEditor::GetPublishLinks()
  6282. {
  6283.     return fPublishLinks;
  6284. }
  6285.  
  6286. //------------------------------------------------------------------------------
  6287. // Method:        ContentUpdated
  6288. // Origin:        DrawEditor
  6289. //
  6290. // Description:    
  6291. //------------------------------------------------------------------------------
  6292. void DrawEditor::ContentUpdated(Environment* ev, ODUpdateID id)
  6293. {
  6294.     
  6295.     if (fLinkStatus == kODInLinkSource)
  6296.     {
  6297.         ODFrame* frame = this->GetFirstSourceFrame(ev);
  6298.         ASSERT_NOT_NULL(frame);
  6299.         
  6300.         if (!id)
  6301.             id = this->GetSession(ev)->UniqueUpdateID(ev);
  6302.             
  6303.         frame->ContentUpdated(ev, id);
  6304.     }
  6305. }
  6306.  
  6307.  
  6308. //------------------------------------------------------------------------------
  6309. // Method:        LinkUpdated
  6310. // Origin:        DrawEditor
  6311. //
  6312. // Description:    
  6313. //------------------------------------------------------------------------------
  6314. void DrawEditor::LinkUpdated(Environment* ev, ODLink* odLink, ODUpdateID updateID)
  6315. {
  6316.     ODBoolean updatedOne = kODFalse;
  6317.     COrderedList badLinkList;
  6318.     
  6319.     ODVolatile(updatedOne);
  6320.     
  6321.     // Notify all the subscribers that are destinations of the updated link
  6322.     COrdListIterator iter(fSubscribeLinks);
  6323.     for (CSubscribeLink* link = (CSubscribeLink*)iter.First(); iter.IsNotComplete(); link = (CSubscribeLink*)iter.Next())
  6324.     {
  6325.         if (odLink->IsEqualTo(ev, link->GetODLink()) && (link->IsRegistered()))
  6326.         {
  6327.             TRY
  6328.                 link->LinkUpdated(ev, updateID);
  6329.                 updatedOne = kODTrue;
  6330.                 
  6331.             CATCH(kODErrCannotEstablishLink)
  6332.  
  6333.                 // Cannot remove link from content model without busting this iterator, so
  6334.                 // make a list. Theoretically there can be only one in this case but...
  6335.                 
  6336.                 badLinkList.AddLast(link);
  6337.                 
  6338.                 // This is supposed to alert user in this case, according to recipe.
  6339.                 // Just beep for now.
  6340.                 
  6341.                 SysBeep(1);
  6342.             CATCH_ALL
  6343.             ENDTRY
  6344.             
  6345.         }
  6346.     }
  6347.     
  6348.     while (badLinkList.Count() != 0)
  6349.     {
  6350.         CSubscribeLink* badLink = (CSubscribeLink*)badLinkList.RemoveFirst();
  6351.         badLink->Unsubscribe(ev);
  6352.         delete badLink;
  6353.     }
  6354.         
  6355.     if (updatedOne)
  6356.     {
  6357.         this->ContentUpdated(ev, updateID);
  6358.         this->SetDirty(ev);
  6359.     }
  6360. }
  6361.  
  6362. //------------------------------------------------------------------------------
  6363. // Method:        GetSelection
  6364. // Origin:        DrawEditor
  6365. //
  6366. // Description:    
  6367. //------------------------------------------------------------------------------
  6368. CSelection* DrawEditor::GetSelection()
  6369. {
  6370.     return fSelection;
  6371. }
  6372.  
  6373.  
  6374. //------------------------------------------------------------------------------
  6375. // Method:        GetPendingPublish
  6376. // Origin:        DrawEditor
  6377. //
  6378. // Description:    
  6379. //------------------------------------------------------------------------------
  6380. CPublishLink* DrawEditor::GetPendingPublish()
  6381. {
  6382.     return fPendingPublish;
  6383. }
  6384.  
  6385. //------------------------------------------------------------------------------
  6386. // Method:        EditInLink
  6387. // Origin:        DrawEditor
  6388. //
  6389. // Description:    
  6390. //------------------------------------------------------------------------------
  6391. void DrawEditor::EditInLink(Environment* ev, CSubscribeLink* link)
  6392. {
  6393.     if (fLinkStatus == kODInLinkDestination)
  6394.     {
  6395.         ODFrame* frame = this->GetFirstSourceFrame(ev);
  6396.         
  6397.         ASSERT_NOT_NULL(frame);
  6398.         
  6399.         frame->EditInLink(ev);
  6400.     }
  6401.     else if (link)
  6402.         // Editing is being unambiguously prevented by a single destination link
  6403.         link->ShowCantEditDialog(ev);
  6404.     else
  6405.         this->ShowCantEditDialog(ev);
  6406. }
  6407.  
  6408. //------------------------------------------------------------------------------
  6409. // Method:        RevealLink
  6410. // Origin:        DrawEditor
  6411. //
  6412. // Description:    
  6413. //------------------------------------------------------------------------------
  6414. void DrawEditor::RevealLink(Environment* ev, ODLinkSource* linkSource)
  6415. {
  6416.     COrdListIterator ite(fPublishLinks);
  6417.     for (CPublishLink *link = (CPublishLink *)ite.First(); ite.IsNotComplete(); link = (CPublishLink *)ite.Next())
  6418.     {
  6419.         if (linkSource->IsEqualTo(ev, link->GetODLinkSource()))
  6420.         {
  6421.             // We've found the link, now we need to find a frame and activate the window and the frame.
  6422.  
  6423.             ODFrame* frame = this->GetFirstSourceFrame(ev);
  6424.             
  6425.             ASSERT_NOT_NULL(frame);
  6426.             
  6427.             // This code is adapted from HandleMouseEvent
  6428.             ODWindow* window = frame->AcquireWindow(ev);
  6429.             ASSERT_NOT_NULL(window);
  6430.  
  6431.             TRY
  6432.                 // Activate inactive windows on the first mouse up event.
  6433.                 if ( !window->IsActive(ev) )
  6434.                     window->Select(ev);
  6435.                                     
  6436.                 // Get our state information from the PartInfo of the frame.
  6437.                 CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  6438.                                 
  6439.                 // If this frame is not the active one, activate it by requesting
  6440.                 // the appropriate foci.
  6441.     
  6442.                 if ( !frameInfo->IsFrameActive() )
  6443.                 {
  6444.                     if ( this->ActivateFrame(ev, frame) )
  6445.                     {
  6446.                         // Keep track of which facet was the last active for positioning
  6447.                         // child windows.  $$$$$ If we need to do this now, then we need a facet.
  6448.                         // frameInfo->SetActiveFacet(facet);
  6449.                     }
  6450.                 }
  6451.             CATCH_ALL
  6452.             ENDTRY
  6453.         
  6454.             // select the link's content
  6455.             link->RevealLink(ev);
  6456.             break;
  6457.         }
  6458.     }
  6459. }
  6460.  
  6461.  
  6462. //------------------------------------------------------------------------------
  6463. // Method:        LinkStatusChanged
  6464. // Origin:        DrawEditor
  6465. //
  6466. // Description:    
  6467. //------------------------------------------------------------------------------
  6468. void DrawEditor::LinkStatusChanged(Environment* ev, ODFrame* frame)
  6469. {
  6470.     // cache whether we're in a link destination for conveience. This is optional
  6471.     fLinkStatus = frame->GetLinkStatus(ev);
  6472.     
  6473.     // Pass the status to our embedded shapes. Those in a subscriber or publisher of this part
  6474.     // should not be changed. One can just pass kODNotInLink, and ChangLinkStatus will insure
  6475.     // that the embedded frame reflects the status of it's containing frame. 
  6476.     
  6477.     COrdListIterator iter(fShapeList);
  6478.     for (CShape * shape = (CShape*)iter.First(); iter.IsNotComplete(); shape = (CShape*)iter.Next())
  6479.     {
  6480.         if ((shape->GetShapeType() == kEmbeddingShape) && !shape->IsPublished() && ! shape->IsSubscribed())
  6481.             ((CEmbeddingShape*)shape)->ChangeLinkStatus(ev, kODNotInLink);
  6482.     }
  6483. }
  6484.  
  6485.  
  6486. //------------------------------------------------------------------------------
  6487. // Method:        ShowCantEditDialog
  6488. // Origin:        DrawEditor
  6489. //
  6490. // Description:    
  6491. //------------------------------------------------------------------------------
  6492. void DrawEditor::ShowCantEditDialog(Environment* ev)
  6493. {
  6494.     // Need to implement the HI specified dialog for when one cannot identify a specific link 
  6495.     // which is preventing editing.
  6496.     
  6497.     SysBeep(1);
  6498.     
  6499. }
  6500.  
  6501.  
  6502. //------------------------------------------------------------------------------
  6503. // Method:        EditInLinkAttempted
  6504. // Origin:        DrawEditor
  6505. //
  6506. // Description:    
  6507. //------------------------------------------------------------------------------
  6508. ODBoolean DrawEditor::EditInLinkAttempted(Environment* ev, ODFrame* frame)
  6509. {
  6510.     CShape* shape = this->ShapeForFrame(ev, frame);
  6511.     
  6512.     CSubscribeLink *sLink = shape->GetSubscribeLink();
  6513.     if (shape && sLink)
  6514.     {
  6515.         sLink->ShowCantEditDialog(ev);
  6516.         return kODTrue;
  6517.     }
  6518.     
  6519.     return kODFalse;  // shouldn't happen under the current linking model.
  6520.     
  6521. }
  6522.  
  6523.  
  6524. //------------------------------------------------------------------------------
  6525. // Method:        GetPendingDragPublish
  6526. // Origin:        DrawEditor
  6527. //
  6528. // Description:    
  6529. //------------------------------------------------------------------------------
  6530. CPublishLink* DrawEditor::GetPendingDragPublish()
  6531. {
  6532.     return fPendingDragPublish;
  6533. }
  6534.  
  6535.  
  6536.  
  6537.  
  6538.  
  6539.